Ejemplo n.º 1
0
    def __init__(self, input_system, output_system):
        super(CoordinateTransform, self).__init__()
        self._input_system_name = input_system
        self._output_system_name = output_system

        if isinstance(self._input_system_name, WCS):
            self.input_system = wcs_to_celestial_frame(self._input_system_name)
        elif isinstance(self._input_system_name, six.string_types):
            self.input_system = frame_transform_graph.lookup_name(self._input_system_name)
            if self.input_system is None:
                raise ValueError("Frame {0} not found".format(self._input_system_name))
        elif isinstance(self._input_system_name, BaseCoordinateFrame):
            self.input_system = self._input_system_name
        else:
            raise TypeError("input_system should be a WCS instance, string, or a coordinate frame instance")

        if isinstance(self._output_system_name, WCS):
            self.output_system = wcs_to_celestial_frame(self._output_system_name)
        elif isinstance(self._output_system_name, six.string_types):
            self.output_system = frame_transform_graph.lookup_name(self._output_system_name)
            if self.output_system is None:
                raise ValueError("Frame {0} not found".format(self._output_system_name))
        elif isinstance(self._output_system_name, BaseCoordinateFrame):
            self.output_system = self._output_system_name
        else:
            raise TypeError("output_system should be a WCS instance, string, or a coordinate frame instance")

        if self.output_system == self.input_system:
            self.same_frames = True
        else:
            self.same_frames = False
Ejemplo n.º 2
0
    def __init__(self, input_system, output_system):
        super().__init__()
        self._input_system_name = input_system
        self._output_system_name = output_system

        if isinstance(self._input_system_name, str):
            self.input_system = frame_transform_graph.lookup_name(
                self._input_system_name)
            if self.input_system is None:
                raise ValueError(f"Frame {self._input_system_name} not found")
        elif isinstance(self._input_system_name, BaseCoordinateFrame):
            self.input_system = self._input_system_name
        else:
            raise TypeError(
                "input_system should be a WCS instance, string, or a coordinate frame instance"
            )

        if isinstance(self._output_system_name, str):
            self.output_system = frame_transform_graph.lookup_name(
                self._output_system_name)
            if self.output_system is None:
                raise ValueError(f"Frame {self._output_system_name} not found")
        elif isinstance(self._output_system_name, BaseCoordinateFrame):
            self.output_system = self._output_system_name
        else:
            raise TypeError(
                "output_system should be a WCS instance, string, or a coordinate frame instance"
            )

        if self.output_system == self.input_system:
            self.same_frames = True
        else:
            self.same_frames = False
Ejemplo n.º 3
0
        def __init__(self, input_system, output_system):
            super(CoordinateTransform, self).__init__()
            self._input_system_name = input_system
            self._output_system_name = output_system

            if isinstance(self._input_system_name, WCS):
                self.input_system = get_coordinate_frame(
                    self._input_system_name)
            elif isinstance(self._input_system_name, six.string_types):
                self.input_system = frame_transform_graph.lookup_name(
                    self._input_system_name)
                if self.input_system is None:
                    raise ValueError("Frame {0} not found".format(
                        self._input_system_name))

            if isinstance(self._output_system_name, WCS):
                self.output_system = get_coordinate_frame(
                    self._output_system_name)
            elif isinstance(self._output_system_name, six.string_types):
                self.output_system = frame_transform_graph.lookup_name(
                    self._output_system_name)
                if self.output_system is None:
                    raise ValueError("Frame {0} not found".format(
                        self._output_system_name))

            if self.output_system == self.input_system:
                self.same_frames = True
            else:
                self.same_frames = False
Ejemplo n.º 4
0
def get_coord_meta(frame):

    coord_meta = {}
    coord_meta['type'] = ('longitude', 'latitude')
    coord_meta['wrap'] = (None, None)
    coord_meta['unit'] = (u.deg, u.deg)

    try:

        from astropy.coordinates import frame_transform_graph

        if isinstance(frame, six.string_types):
            frame = frame_transform_graph.lookup_name(frame)

        names = list(frame().representation_component_names.keys())
        coord_meta['name'] = names[:2]

    except ImportError:

        if isinstance(frame, six.string_types):
            if frame in ('fk4', 'fk5', 'icrs'):
                coord_meta['name'] = ('ra', 'dec')
            elif frame == 'galactic':
                coord_meta['name'] = ('l', 'b')
            else:
                raise ValueError("Unknown frame: {0}".format(frame))

    return coord_meta
Ejemplo n.º 5
0
    def __str__(self):

        """
        This function ...
        :return:
        """

        if self.include: prefix = ""
        else: prefix = "-"

        coordsys = 'fk5'
        fmt = '.4f'
        radunit = 'deg'

        if radunit == 'arcsec':
            if coordsys in coordsys_name_mapping.keys(): radunitstr = '"'
            else: raise ValueError('Radius unit arcsec not valid for coordsys {}'.format(coordsys))
        else: radunitstr = ''

        # convert coordsys string to coordsys object
        if coordsys in coordsys_name_mapping: frame = frame_transform_graph.lookup_name(coordsys_name_mapping[coordsys])
        else: frame = None  # for pixel/image/physical frames

        x = float(self.start.transform_to(frame).spherical.lon.to('deg').value)
        y = float(self.start.transform_to(frame).spherical.lat.to('deg').value)
        l = float(self.length.to(radunit).value)
        ang = float(self.angle.to('deg').value)

        string = prefix + make_vector_template(fmt, radunitstr).format(**locals())
        string = add_info(string, self)
        return string
Ejemplo n.º 6
0
def parse_coord_system(system):

    if isinstance(system, BaseCoordinateFrame):

        return system

    elif isinstance(system, six.string_types):

        system = system.lower()

        if system == 'e':
            raise ValueError("Ecliptic coordinate frame not yet supported")

        elif system in FRAMES:

            return FRAMES[system]

        else:

            system_new = frame_transform_graph.lookup_name(system)

            if system_new is None:

                raise ValueError(
                    "Could not determine frame for system={0}".format(system))

            else:

                return system_new()
Ejemplo n.º 7
0
Archivo: point.py Proyecto: rag9704/PTS
    def __str__(self):
        """
        This function ...
        :return:
        """

        coordsys = "fk5"
        # convert coordsys string to coordsys object
        if coordsys in coordsys_name_mapping:
            frame = frame_transform_graph.lookup_name(
                coordsys_name_mapping[coordsys])
        else:
            frame = None  # for pixel/image/physical frames

        fmt = '.4f'

        if self.include: prefix = ""
        else: prefix = "-"

        x = float(self.transform_to(frame).spherical.lon.to('deg').value)
        y = float(self.transform_to(frame).spherical.lat.to('deg').value)

        string = prefix + make_point_template(fmt).format(**locals())
        string = add_info(string, self)
        return string
Ejemplo n.º 8
0
Archivo: polygon.py Proyecto: SKIRT/PTS
    def __str__(self):

        """
        This function ...
        :return:
        """

        if self.include: prefix = ""
        else: prefix = "-"

        coordsys = 'fk5'
        fmt = '.4f'
        radunit = 'deg'

        if radunit == 'arcsec':
            if coordsys in coordsys_name_mapping.keys(): radunitstr = '"'
            else: raise ValueError('Radius unit arcsec not valid for coordsys {}'.format(coordsys))
        else: radunitstr = ''

        # convert coordsys string to coordsys object
        if coordsys in coordsys_name_mapping: frame = frame_transform_graph.lookup_name(coordsys_name_mapping[coordsys])
        else: frame = None  # for pixel/image/physical frames

        v = self.points.transform_to(frame)
        coords = [(x.to('deg').value, y.to('deg').value) for x, y in
                  zip(v.spherical.lon, v.spherical.lat)]
        val = "{:" + fmt + "}"
        temp = [val.format(x) for _ in coords for x in _]
        c = ",".join(temp)

        string = prefix + make_polygon_template().format(**locals())
        string = add_info(string, self)
        return string
Ejemplo n.º 9
0
def get_coord_meta(frame):

    coord_meta = {}
    coord_meta['type'] = ('longitude', 'latitude')
    coord_meta['wrap'] = (None, None)
    coord_meta['unit'] = (u.deg, u.deg)

    try:

        from astropy.coordinates import frame_transform_graph

        if isinstance(frame, six.string_types):
            frame = frame_transform_graph.lookup_name(frame)

        names = list(frame().representation_component_names.keys())
        coord_meta['name'] = names[:2]

    except ImportError:

        if isinstance(frame, six.string_types):
            if frame in ('fk4', 'fk5', 'icrs'):
                coord_meta['name'] = ('ra', 'dec')
            elif frame == 'galactic':
                coord_meta['name'] = ('l', 'b')
            else:
                raise ValueError("Unknown frame: {0}".format(frame))

    return coord_meta
Ejemplo n.º 10
0
Archivo: line.py Proyecto: rag9704/PTS
    def __str__(self):

        """
        This function ...
        :return:
        """

        coordsys = "fk5"
        # convert coordsys string to coordsys object
        if coordsys in coordsys_name_mapping: frame = frame_transform_graph.lookup_name(coordsys_name_mapping[coordsys])
        else: frame = None  # for pixel/image/physical frames

        fmt = '.4f'

        if self.include: prefix = ""
        else: prefix = "-"

        x1 = float(self.start.transform_to(frame).spherical.lon.to('deg').value)
        y1 = float(self.start.transform_to(frame).spherical.lat.to('deg').value)

        x2 = float(self.end.transform_to(frame).spherical.lon.to('deg').value)
        y2 = float(self.end.transform_to(frame).spherical.lat.to('deg').value)

        # TO HAVE IT IN hh:mm:ss NOTATION:

        # print(vars(reg.start.transform_to(frame)))
        # skycoordinate = SkyCoordinate(reg.start.transform_to(frame).spherical.lon, reg.start.transform_to(frame).spherical.lat, frame=frame, representation="spherical")
        # str1 = skycoordinate.to_string('hmsdms').replace("d", ":").replace("h", ":").replace("m", ":").replace("s ", ",")[:-1]

        # skycoordinate = SkyCoordinate(reg.end.transform_to(frame).spherical.lon, reg.end.transform_to(frame).spherical.lat, frame=frame, representation="spherical")
        # str2 = skycoordinate.to_string('hmsdms').replace("d", ":").replace("h", ":").replace("m", ":").replace("s ", ",")[:-1]

        string = prefix + make_line_template(fmt).format(**locals())
        string = add_info(string, self)
        return string
Ejemplo n.º 11
0
Archivo: text.py Proyecto: SKIRT/PTS
    def __str__(self):

        """
        This function ...
        :return:
        """

        if self.include: prefix = ""
        else: prefix = "-"

        coordsys = 'fk5'
        fmt = '.4f'
        radunit = 'deg'

        if radunit == 'arcsec':
            if coordsys in coordsys_name_mapping.keys(): radunitstr = '"'
            else: raise ValueError('Radius unit arcsec not valid for coordsys {}'.format(coordsys))
        else: radunitstr = ''

        # convert coordsys string to coordsys object
        if coordsys in coordsys_name_mapping: frame = frame_transform_graph.lookup_name(coordsys_name_mapping[coordsys])
        else: frame = None  # for pixel/image/physical frames

        x = float(self.center.transform_to(frame).spherical.lon.to('deg').value)
        y = float(self.center.transform_to(frame).spherical.lat.to('deg').value)
        text = self.text

        string = prefix + make_text_template(fmt).format(**locals())
        string = add_info(string, self)
        return string
Ejemplo n.º 12
0
    def __init__(self, input_system, output_system):
        super(CoordinateTransform, self).__init__()
        self._input_system_name = input_system
        self._output_system_name = output_system

        if isinstance(self._input_system_name, WCS):
            self.input_system = wcs_to_celestial_frame(self._input_system_name)
        elif isinstance(self._input_system_name, six.string_types):
            self.input_system = frame_transform_graph.lookup_name(
                self._input_system_name)
            if self.input_system is None:
                raise ValueError("Frame {0} not found".format(
                    self._input_system_name))
        elif isinstance(self._input_system_name, BaseCoordinateFrame):
            self.input_system = self._input_system_name
        else:
            raise TypeError(
                "input_system should be a WCS instance, string, or a coordinate frame instance"
            )

        if isinstance(self._output_system_name, WCS):
            self.output_system = wcs_to_celestial_frame(
                self._output_system_name)
        elif isinstance(self._output_system_name, six.string_types):
            self.output_system = frame_transform_graph.lookup_name(
                self._output_system_name)
            if self.output_system is None:
                raise ValueError("Frame {0} not found".format(
                    self._output_system_name))
        elif isinstance(self._output_system_name, BaseCoordinateFrame):
            self.output_system = self._output_system_name
        else:
            raise TypeError(
                "output_system should be a WCS instance, string, or a coordinate frame instance"
            )

        if self.output_system == self.input_system:
            self.same_frames = True
        else:
            self.same_frames = False
Ejemplo n.º 13
0
        def __init__(self, input_system, output_system):
            super(CoordinateTransform, self).__init__()
            self._input_system_name = input_system
            self._output_system_name = output_system

            if isinstance(self._input_system_name, WCS):
                self.input_system = get_coordinate_frame(self._input_system_name)
            elif isinstance(self._input_system_name, six.string_types):
                self.input_system = frame_transform_graph.lookup_name(self._input_system_name)
                if self.input_system is None:
                    raise ValueError("Frame {0} not found".format(self._input_system_name))

            if isinstance(self._output_system_name, WCS):
                self.output_system = get_coordinate_frame(self._output_system_name)
            elif isinstance(self._output_system_name, six.string_types):
                self.output_system = frame_transform_graph.lookup_name(self._output_system_name)
                if self.output_system is None:
                    raise ValueError("Frame {0} not found".format(self._output_system_name))

            if self.output_system == self.input_system:
                self.same_frames = True
            else:
                self.same_frames = False
Ejemplo n.º 14
0
def parse_coord_system(system):
    if isinstance(system, BaseCoordinateFrame):
        return system
    elif isinstance(system, six.string_types):
        system = system.lower()
        if system == 'e':
            raise ValueError("Ecliptic coordinate frame not yet supported")
        elif system in FRAMES:
            return FRAMES[system]
        else:
            system_new = frame_transform_graph.lookup_name(system)
            if system_new is None:
                raise ValueError("Could not determine frame for system={0}".format(system))
            else:
                return system_new()
Ejemplo n.º 15
0
Archivo: ellipse.py Proyecto: SKIRT/PTS
    def __str__(self):

        """
        This function ...
        :return:
        """

        if self.include: prefix = ""
        else: prefix = "-"

        coordsys = 'fk5'
        fmt = '.4f'
        #radunit = 'deg'
        radunit = "arcsec"

        if radunit == 'arcsec':
            if coordsys in coordsys_name_mapping.keys(): radunitstr = '"'
            else: raise ValueError('Radius unit arcsec not valid for coordsys {}'.format(coordsys))
        else: radunitstr = ''

        # convert coordsys string to coordsys object
        if coordsys in coordsys_name_mapping: frame = frame_transform_graph.lookup_name(coordsys_name_mapping[coordsys])
        else: frame = None  # for pixel/image/physical frames

        x = float(self.center.transform_to(frame).spherical.lon.to('deg').value)
        y = float(self.center.transform_to(frame).spherical.lat.to('deg').value)
        ra = coordinates.degrees_to_hms(ra=x)
        dec = coordinates.degrees_to_hms(dec=y)
        x = ra
        y = dec
        r1 = float(self.semimajor.to(radunit).value)
        r2 = float(self.semiminor.to(radunit).value)
        ang = float(self.angle.to('deg').value)

        #preprefix = coordsys + ";"
        preprefix = ""

        string = preprefix + prefix + make_ellipse_template(fmt, radunitstr, hmsdms=True).format(**locals())
        string = add_info(string, self)
        return string
Ejemplo n.º 16
0
    def __str__(self):
        """
        This function ...
        :return:
        """

        if self.include: prefix = ""
        else: prefix = "-"

        coordsys = 'fk5'
        fmt = '.4f'
        radunit = 'deg'

        if radunit == 'arcsec':
            if coordsys in coordsys_name_mapping.keys(): radunitstr = '"'
            else:
                raise ValueError(
                    'Radius unit arcsec not valid for coordsys {}'.format(
                        coordsys))
        else:
            radunitstr = ''

        # convert coordsys string to coordsys object
        if coordsys in coordsys_name_mapping:
            frame = frame_transform_graph.lookup_name(
                coordsys_name_mapping[coordsys])
        else:
            frame = None  # for pixel/image/physical frames

        v = self.points.transform_to(frame)
        coords = [(x.to('deg').value, y.to('deg').value)
                  for x, y in zip(v.spherical.lon, v.spherical.lat)]
        val = "{:" + fmt + "}"
        temp = [val.format(x) for _ in coords for x in _]
        c = ",".join(temp)

        string = prefix + make_polygon_template().format(**locals())
        string = add_info(string, self)
        return string
Ejemplo n.º 17
0
def get_coord_meta(frame):

    coord_meta = {}
    coord_meta['type'] = ('longitude', 'latitude')
    coord_meta['wrap'] = (None, None)
    coord_meta['unit'] = (u.deg, u.deg)

    from astropy.coordinates import frame_transform_graph

    if isinstance(frame, str):
        initial_frame = frame
        frame = frame_transform_graph.lookup_name(frame)
        if frame is None:
            raise ValueError("Unknown frame: {0}".format(initial_frame))

    if not isinstance(frame, BaseCoordinateFrame):
        frame = frame()

    names = list(frame.representation_component_names.keys())
    coord_meta['name'] = names[:2]

    return coord_meta
Ejemplo n.º 18
0
def get_coord_meta(frame):

    coord_meta = {}
    coord_meta['type'] = ('longitude', 'latitude')
    coord_meta['wrap'] = (None, None)
    coord_meta['unit'] = (u.deg, u.deg)

    from astropy.coordinates import frame_transform_graph

    if isinstance(frame, six.string_types):
        initial_frame = frame
        frame = frame_transform_graph.lookup_name(frame)
        if frame is None:
            raise ValueError("Unknown frame: {0}".format(initial_frame))

    if not isinstance(frame, BaseCoordinateFrame):
        frame = frame()

    names = list(frame.representation_component_names.keys())
    coord_meta['name'] = names[:2]

    return coord_meta
Ejemplo n.º 19
0
Archivo: point.py Proyecto: SKIRT/PTS
    def __str__(self):

        """
        This function ...
        :return:
        """

        coordsys = "fk5"
        # convert coordsys string to coordsys object
        if coordsys in coordsys_name_mapping: frame = frame_transform_graph.lookup_name(coordsys_name_mapping[coordsys])
        else: frame = None  # for pixel/image/physical frames

        fmt = '.4f'

        if self.include: prefix = ""
        else: prefix = "-"

        x = float(self.transform_to(frame).spherical.lon.to('deg').value)
        y = float(self.transform_to(frame).spherical.lat.to('deg').value)

        string = prefix + make_point_template(fmt).format(**locals())
        string = add_info(string, self)
        return string
Ejemplo n.º 20
0
def find_optimal_celestial_wcs(input_data,
                               frame=None,
                               auto_rotate=False,
                               projection='TAN',
                               resolution=None,
                               reference=None):
    """
    Given one or more images, return an optimal WCS projection object and
    shape.

    This currently only works with 2-d images with celestial WCS.

    Parameters
    ----------
    input_data : iterable
        One or more input data specifications to include in the calculation of
        the final WCS. This should be an iterable containing one entry for each
        specification, where a single data specification is one of:

            * The name of a FITS file
            * An `~astropy.io.fits.HDUList` object
            * An image HDU object such as a `~astropy.io.fits.PrimaryHDU`,
              `~astropy.io.fits.ImageHDU`, or `~astropy.io.fits.CompImageHDU`
              instance
            * A tuple where the first element is an Numpy array shape tuple
              the second element is either a `~astropy.wcs.WCS` or a
              `~astropy.io.fits.Header` object
            * A tuple where the first element is a `~numpy.ndarray` and the
              second element is either a `~astropy.wcs.WCS` or a
              `~astropy.io.fits.Header` object

    frame : str or `~astropy.coordinates.BaseCoordinateFrame`
        The coordinate system for the final image (defaults to the frame of
        the first image specified)
    auto_rotate : bool
        Whether to rotate the header to minimize the final image area (if
        `True`, requires shapely>=1.6 to be installed)
    projection : str
        Three-letter code for the WCS projection
    resolution : `~astropy.units.Quantity`
        The resolution of the final image. If not specified, this is the
        smallest resolution of the input images.
    reference : `~astropy.coordinates.SkyCoord`
        The reference coordinate for the final header. If not specified, this
        is determined automatically from the input images.

    Returns
    -------
    wcs : :class:`~astropy.wcs.WCS`
        The optimal WCS determined from the input images.
    shape : tuple
        The optimal shape required to cover all the output.
    """

    # TODO: support higher-dimensional datasets in future
    # TODO: take into account NaN values when determining the extent of the
    #       final WCS

    if isinstance(frame, str):
        frame = frame_transform_graph.lookup_name(frame)()

    input_shapes = [parse_input_shape(shape) for shape in input_data]

    # We start off by looping over images, checking that they are indeed
    # celestial images, and building up a list of all corners and all reference
    # coordinates in celestial (ICRS) coordinates.

    corners = []
    references = []
    resolutions = []

    for shape, wcs in input_shapes:

        if len(shape) != 2:
            raise ValueError(
                "Input data is not 2-dimensional (got shape {!r})".format(
                    shape))

        if wcs.naxis != 2:
            raise ValueError("Input WCS is not 2-dimensional")

        if not wcs.has_celestial:
            raise TypeError("WCS does not have celestial components")

        # Determine frame if it wasn't specified
        if frame is None:
            frame = wcs_to_celestial_frame(wcs)

        # Find pixel coordinates of corners. In future if we are worried about
        # significant distortions of the edges in the reprojection process we
        # could simply add arbitrary numbers of midpoints to this list.
        ny, nx = shape
        xc = np.array([-0.5, nx - 0.5, nx - 0.5, -0.5])
        yc = np.array([-0.5, -0.5, ny - 0.5, ny - 0.5])

        # We have to do .frame here to make sure that we get an ICRS object
        # without any 'hidden' attributes, otherwise the stacking below won't
        # work. TODO: check if we need to enable distortions here.
        corners.append(pixel_to_skycoord(xc, yc, wcs, origin=0).icrs.frame)

        # We now figure out the reference coordinate for the image in ICRS. The
        # easiest way to do this is actually to use pixel_to_skycoord with the
        # reference position in pixel coordinates. We have to set origin=1
        # because crpix values are 1-based.
        xp, yp = wcs.wcs.crpix
        references.append(pixel_to_skycoord(xp, yp, wcs, origin=1).icrs.frame)

        # Find the pixel scale at the reference position - we take the minimum
        # since we are going to set up a header with 'square' pixels with the
        # smallest resolution specified.
        scales = proj_plane_pixel_scales(wcs)
        resolutions.append(np.min(np.abs(scales)))

    # We now stack the coordinates - however the ICRS class can't do this
    # so we have to use the high-level SkyCoord class.
    corners = SkyCoord(corners)
    references = SkyCoord(references)

    # If no reference coordinate has been passed in for the final header, we
    # determine the reference coordinate as the mean of all the reference
    # positions. This choice is as good as any and if the user really cares,
    # they can set  it manually.
    if reference is None:
        reference = SkyCoord(references.data.mean(), frame=references.frame)

    # In any case, we need to convert the reference coordinate (either
    # specified or automatically determined) to the requested final frame.
    reference = reference.transform_to(frame)

    # Determine resolution if not specified
    if resolution is None:
        resolution = np.min(resolutions) * u.deg

    # Determine the resolution in degrees
    cdelt = resolution.to(u.deg).value

    # Construct WCS object centered on position
    wcs_final = celestial_frame_to_wcs(frame, projection=projection)

    rep = reference.represent_as('unitspherical')
    wcs_final.wcs.crval = rep.lon.degree, rep.lat.degree
    wcs_final.wcs.cdelt = -cdelt, cdelt

    # For now, set crpix to (1, 1) and we'll then figure out where all the
    # images fall in this projection, then we'll adjust crpix.
    wcs_final.wcs.crpix = (1, 1)

    # Find pixel coordinates of all corners in the final WCS projection. We use
    # origin=1 since we are trying to determine crpix values.
    xp, yp = skycoord_to_pixel(corners, wcs_final, origin=1)

    if auto_rotate:

        # Use shapely to represent the points and find the minimum rotated
        # rectangle
        from shapely.geometry import MultiPoint
        mp = MultiPoint(list(zip(xp, yp)))

        # The following returns a list of rectangle vertices - in fact there
        # are 5 coordinates because shapely represents it as a closed polygon
        # with the same first/last vertex.
        xr, yr = mp.minimum_rotated_rectangle.exterior.coords.xy
        xr, yr = xr[:4], yr[:4]

        # The order of the vertices is not guaranteed to be constant so we
        # take the vertices with the two smallest y values (which, for a
        # rectangle, guarantees that the vertices are neighboring)
        order = np.argsort(yr)
        x1, y1, x2, y2 = xr[order[0]], yr[order[0]], xr[order[1]], yr[order[1]]

        # Determine angle between two of the vertices. It doesn't matter which
        # ones they are, we just want to know how far from being straight the
        # rectangle is.
        angle = np.arctan2(y2 - y1, x2 - x1)

        # Determine the smallest angle that would cause the rectangle to be
        # lined up with the axes.
        angle = angle % (np.pi / 2)
        if angle > np.pi / 4:
            angle -= np.pi / 2

        # Set rotation matrix (use PC instead of CROTA2 since PC is the
        # recommended approach)
        pc = np.array([[np.cos(angle), -np.sin(angle)],
                       [np.sin(angle), np.cos(angle)]])
        wcs_final.wcs.pc = pc

        # Recompute pixel coordinates (more accurate than simply rotating xp, yp)
        xp, yp = skycoord_to_pixel(corners, wcs_final, origin=1)

    # Find the full range of values
    xmin = xp.min()
    xmax = xp.max()
    ymin = yp.min()
    ymax = yp.max()

    # Update crpix so that the lower range falls on the bottom and left. We add
    # 0.5 because in the final image the bottom left corner should be at (0.5,
    # 0.5) not (1, 1).
    wcs_final.wcs.crpix = (1 - xmin) + 0.5, (1 - ymin) + 0.5

    # Return the final image shape too
    naxis1 = int(round(xmax - xmin))
    naxis2 = int(round(ymax - ymin))

    return wcs_final, (naxis2, naxis1)
Ejemplo n.º 21
0
def _parse_args(args):
    # first try pulling out separate coordinates
    c1 = args.pop('coord1', None)
    c2 = args.pop('coord2', None)
    cargs = (c1, c2)

    # if either are None, check for a coordstr
    if c1 is None or c2 is None:
        coordstr = args.pop('coordstr', None)
        cargs = (coordstr,)

    if (c1 is None or c2 is None) and (coordstr is None):
        # TODO: throw a error
        raise ValueError("Shitty arguments, yo.")

    # default units are degrees
    c1u = u.Unit(args.pop('coord1unit', u.deg))
    c2u = u.Unit(args.pop('coord2unit', u.deg))

    to_system = args.pop('to')
    from_system = args.pop('from')

    # extra arguments to pass to the coordinate frames
    fromargs = dict()
    toargs = dict()
    for k, v in args.items():
        if k.startswith('from_'):
            fromargs[k.split('from_')[1]] = v

        if k.startswith('to_'):
            toargs[k.split('to_')[1]] = v

    fromargs['frame'] = from_system.lower()

    # get the 'to' frame class
    ToFrame = frame_transform_graph.lookup_name(to_system.lower())

    c = SkyCoord(*cargs, unit=(c1u, c2u), **fromargs).transform_to(frame=ToFrame(**toargs))

    comps = []
    for compnm in c.representation_component_names:
        compval = getattr(c, compnm)
        uout = c.representation_component_units.get(compnm, None)
        if uout is not None:
            compval.to(uout)
        comps.append((compnm, compval))

    output = {}
    for i, (compnm, comp) in enumerate(comps):
        # container for information for this coordinate
        this_coord = dict()

        ip1s = str(i + 1)
        if not isiterable(comp.value):
            val = [comp.value]
        else:
            val = comp.value

        this_coord['data'] = list(val)
        this_coord['name'] = compnm
        this_coord['unit'] = str(comp.unit)
        output['coord' + ip1s] = this_coord

    for fattr_nm in c.get_frame_attr_names():
        output['frame_' + fattr_nm] = str(getattr(c, fattr_nm))

    return output
Ejemplo n.º 22
0
def init_pvt(frame, time, pos, vel=None, copy=False):
    """
    Convenience method to initialise a `SkyCoord` object using the inputs.

    If velocity input is not given (or is `None`), then velocity input is not set.
    If a velocity value of (0,0,0) is desired, these values should be explicitly
    assigned and the corresponding velocity vector should be given as input.

    Note that, the position vector input may be including the velocity inputs. If
    velocity input is not given, then these velocity values are not overwritten.

    Also note that, `Time`, `CartesianRepresentation` and `CartesianDifferential`
    objects as well as the resulting `SkyCoord` object support multiple value inputs,
    as long as the input sizes match. As an example, it is possible to input
    30 time, position and velocity values, representing discrete points on
    a trajectory.

    Parameters
    ----------
    frame : str or Type[BaseCoordinateFrame]
        Frame name (string) or frame object itself (e.g.GCRS)
    time : Time
        time(s) associated with the coordinates
    pos : CartesianRepresentation
        Position vector(s)
    vel : CartesianDifferential or None
        Velocity vector(s)
    copy : bool, optional
        If `True` (default), a copy of any coordinate data is made.

    Returns
    -------
    SkyCoord
        `SkyCoord` object representing the cartesian input
    """

    if isinstance(frame, str):
        # frame is defined with its name, try to identify it
        rv_frame = frame_transform_graph.lookup_name(frame.lower())
        if not rv_frame:
            raise ValueError(
                f"Frame name {frame} not recognised as a valid frame name.")
    else:
        # frame is (hopefully) defined with an object
        rv_frame = frame

    if not isinstance(time, Time):
        raise TypeError(
            f"Time input ({time}) not recognised as a valid Time object.")

    # All is ready, init the frame object
    try:
        # Certain coordinate frames (notably ICRS) don't like obstime, check for this
        if vel:
            rv_skycoord = rv_frame(
                pos.with_differentials(vel),
                obstime=time,
                representation_type="cartesian",
                differential_type="cartesian",
            )
        else:
            rv_skycoord = rv_frame(
                pos,
                obstime=time,
                representation_type="cartesian",
                differential_type="cartesian",
                copy=copy,
            )

        return SkyCoord(rv_skycoord, copy=copy)
    except TypeError:
        if vel:
            rv_skycoord = rv_frame(
                pos.with_differentials(vel),
                representation_type="cartesian",
                differential_type="cartesian",
            )
        else:
            rv_skycoord = rv_frame(
                pos,
                representation_type="cartesian",
                differential_type="cartesian",
                copy=copy,
            )

        return SkyCoord(
            rv_skycoord,
            obstime=time,
            representation_type="cartesian",
            differential_type="cartesian",
            copy=copy,
        )