Esempio n. 1
0
def areaint(lats, lons):
    assert lats.size == lons.size, 'List of latitudes and longitudes are different sizes.'

    if isinstance(lats.iloc[0], u.Quantity):
        lat = np.array([lat.value
                        for lat in lats] + [lats.iloc[0].value]) * u.deg
        lon = np.array([lon.value
                        for lon in lons] + [lons.iloc[0].value]) * u.deg
    else:
        lat = np.append(lats, lats.iloc[0]) * u.deg
        lon = np.append(lons, lons.iloc[0]) * u.deg

    if lat.max() > 0:
        northern = True

    # Get colatitude (a measure of surface distance as an angle) and
    # azimuth of each point in segment from the center of mass.

    _, center_lat, center_lon = sph_center_of_mass(lat[:-1], lon[:-1])

    if np.isnan(center_lat.value):
        center_lat = Latitude(0, unit=u.rad)

    if np.isnan(center_lon.value):
        center_lon = Longitude(0, unit=u.rad)

    # force centroid at the N or S pole
    # if northern:
    #    center_lat = 90 * u.deg
    # else:
    #   center_lat = -90 * u.deg
    # center_lon = 0 * u.deg

    colat = np.array([
        distance(center_lon.to(u.deg), center_lat.to(u.deg), longi, latit).to(
            u.deg).value for latit, longi in zip(lat, lon)
    ]) * u.deg
    az = np.array([
        azimuth(center_lon.to(u.deg), center_lat.to(u.deg), longi, latit).to(
            u.deg).value for latit, longi in zip(lat, lon)
    ]) * u.deg

    # Calculate step sizes, taking the complementary angle where needed
    daz = np.diff(az).to(u.rad)
    daz[np.where(daz > 180 * u.deg)] -= 360. * u.deg
    daz[np.where(daz < -180 * u.deg)] += 360. * u.deg

    # Determine average surface distance for each step
    deltas = np.diff(colat) / 2.
    colats = colat[0:-1] + deltas

    # Integral over azimuth is 1-cos(colatitudes)
    integrands = (1 - np.cos(colats)) * daz

    # Integrate and return the answer as a fraction of the unit sphere.
    # Note that the sum of the integrands will include a part of 4pi.

    return np.abs(
        np.nansum(integrands)) / (4 * np.pi * u.rad), center_lat, center_lon
Esempio n. 2
0
def location(lat, lon, alt):

    # Reference location
    lon = Longitude(lon.strip(),
                    u.degree,
                    wrap_angle=180 * u.degree,
                    copy=False)  # noqa
    lat = Latitude(lat.strip(), u.degree, copy=False)
    height = u.Quantity(float(alt.strip()), u.m, copy=False)
    ref_location = EarthLocation(lat=lat.to(u.deg).value,
                                 lon=lon.to(u.deg).value,
                                 height=height.to(u.m).value)  # noqa

    return ref_location
def gmst2time(gmst, time):
        """
        Converts a Greenwich Mean Sidereal Time to UTC time, for a given date.

        Parameters
        ----------
        gmst: ~float
            Greenwich Mean Siderial Time (hours)
        time : astropy.time.Time
            UT date+time

        Returns
        -------
        astropy.time.Time object with closest UT day+time at which
            siderial time is correct.
        """
        dgmst = Longitude(gmst - time2gmst(time))
        return time+TimeDelta(dgmst.to(u.hourangle).value*0.9972695663/24.,
                              format='jd')
Esempio n. 4
0
    def pixel_to_data(self, x, y, origin=0):
        """
        Convert a pixel coordinate to a data (world) coordinate by using
        `~astropy.wcs.WCS.wcs_pix2world`.

        Parameters
        ----------

        x : float
            Pixel coordinate of the CTYPE1 axis. (Normally solar-x).

        y : float
            Pixel coordinate of the CTYPE2 axis. (Normally solar-y).

        origin : int
            Origin of the top-left corner. i.e. count from 0 or 1.
            Normally, origin should be 0 when passing numpy indices, or 1 if
            passing values from FITS header or map attributes.
            See `~astropy.wcs.WCS.wcs_pix2world` for more information.

        Returns
        -------

        x : `~astropy.units.Quantity`
            Coordinate of the CTYPE1 axis. (Normally solar-x).

        y : `~astropy.units.Quantity`
            Coordinate of the CTYPE2 axis. (Normally solar-y).
        """
        x, y = self.wcs.wcs_pix2world(x, y, origin)

        # If the wcs is celestial it is output in degress
        if self.wcs.is_celestial:
            x *= u.deg
            y *= u.deg
        else:
            x *= self.units.x
            y *= self.units.y

        x = Longitude(x, wrap_angle=180 * u.deg)
        y = Latitude(y)

        return x.to(self.units.x), y.to(self.units.y)
Esempio n. 5
0
def gmst2time(gmst, time):
    """
        Converts a Greenwich Mean Sidereal Time to UTC time, for a given date.

        Parameters
        ----------
        gmst: ~float
            Greenwich Mean Siderial Time (hours)
        time : astropy.time.Time
            UT date+time

        Returns
        -------
        astropy.time.Time object with closest UT day+time at which
            siderial time is correct.
        """
    dgmst = Longitude(gmst - time2gmst(time))
    return time + TimeDelta(dgmst.to(u.hourangle).value * 0.9972695663 / 24.,
                            format='jd',
                            scale='utc')
Esempio n. 6
0
def rot_hpc(x, y, tstart, tend, frame_time='synodic', rot_type='howard', **kwargs):
    """Given a location on the Sun referred to using the Helioprojective
    Cartesian co-ordinate system (typically quoted in the units of arcseconds)
    use the solar rotation profile to find that location at some later or
    earlier time.  Note that this function assumes that the data was observed
    from the Earth or near Earth vicinity.  Specifically, data from SOHO and
    STEREO observatories are not supported.  Note also that the function does
    NOT use solar B0 and L0 values provided in source FITS files - these
    quantities are calculated.

    Parameters
    ----------
    x : `~astropy.units.Quantity`
        Helio-projective x-co-ordinate in arcseconds (can be an array).

    y : `~astropy.units.Quantity`
        Helio-projective y-co-ordinate in arcseconds (can be an array).

    tstart : `sunpy.time.time`
        date/time to which x and y are referred.

    tend : `sunpy.time.time`
    date/time at which x and y will be rotated to.

    rot_type : {'howard' | 'snodgrass' | 'allen'}
        | howard: Use values for small magnetic features from Howard et al.
        | snodgrass: Use Values from Snodgrass et. al
        | allen: Use values from Allen, Astrophysical Quantities, and simpler
          equation.

    frame_time: {'sidereal' | 'synodic'}
        Choose type of day time reference frame.

    Returns
    -------
    x : `~astropy.units.Quantity`
        Rotated helio-projective x-co-ordinate in arcseconds (can be an array).

    y : `~astropy.units.Quantity`
        Rotated helio-projective y-co-ordinate in arcseconds (can be an array).

    Examples
    --------
    >>> import astropy.units as u
    >>> from sunpy.physics.transforms.differential_rotation import rot_hpc
    >>> rot_hpc( -570 * u.arcsec, 120 * u.arcsec, '2010-09-10 12:34:56', '2010-09-10 13:34:56')
    (<Angle -562.9105822671319 arcsec>, <Angle 119.31920621992195 arcsec>)

    Notes
    -----
    SSWIDL code equivalent: http://hesperia.gsfc.nasa.gov/ssw/gen/idl/solar/rot_xy.pro .
    The function rot_xy uses arcmin2hel.pro and hel2arcmin.pro to implement the
    same functionality as this function.  These two functions seem to perform
    inverse operations of each other to a high accuracy.  The corresponding
    equivalent functions here are convert_hpc_hg and convert_hg_hpc
    respectively. These two functions seem to perform inverse
    operations of each other to a high accuracy.  However, the values
    returned by arcmin2hel.pro are slightly different from those provided
    by convert_hpc_hg.  This leads to very slightly different results from
    rot_hpc compared to rot_xy.
    """

    # must have pairs of co-ordinates
    if np.array(x).shape != np.array(y).shape:
        raise ValueError('Input co-ordinates must have the same shape.')

    # Make sure we have enough time information to perform a solar differential
    # rotation
    # Start time
    dstart = parse_time(tstart)
    dend = parse_time(tend)
    interval = (dend - dstart).total_seconds() * u.s

    # Get the Sun's position from the vantage point at the start time
    vstart = kwargs.get("vstart", _calc_P_B0_SD(dstart))
    # Compute heliographic co-ordinates - returns (longitude, latitude). Points
    # off the limb are returned as nan
    longitude, latitude = convert_hpc_hg(x.to(u.arcsec).value,
                                         y.to(u.arcsec).value,
                                         b0_deg=vstart["b0"].to(u.deg).value,
                                         l0_deg=vstart["l0"].to(u.deg).value, 
                                         dsun_meters=(constants.au * sun.sunearth_distance(t=dstart)).value,
                                         angle_units='arcsec')
    longitude = Longitude(longitude, u.deg)
    latitude = Angle(latitude, u.deg)
    # Compute the differential rotation
    drot = diff_rot(interval, latitude, frame_time=frame_time,
                    rot_type=rot_type)

    # Convert back to heliocentric cartesian in units of arcseconds
    vend = kwargs.get("vend", _calc_P_B0_SD(dend))

    # It appears that there is a difference in how the SSWIDL function
    # hel2arcmin and the sunpy function below performs this co-ordinate
    # transform.
    newx, newy = convert_hg_hpc(longitude.to(u.deg).value + drot.to(u.deg).value,
                                latitude.to(u.deg).value,
                                b0_deg=vend["b0"].to(u.deg).value,
                                l0_deg=vend["l0"].to(u.deg).value,
                                dsun_meters=(constants.au * sun.sunearth_distance(t=dend)).value,
                                occultation=False)
    newx = Angle(newx, u.arcsec)
    newy = Angle(newy, u.arcsec)
    return newx.to(u.arcsec), newy.to(u.arcsec)