예제 #1
0
def set_bary_helio_times(filename, jwstpos=None):
    '''
    Compute the barycentric and heliocentric times for the
    given file and update the contents of the file to contain
    these values.
    '''
    print('Starting set_bary_helio_times task')
    hdul = fits.open(filename, mode='update')
    pheader = hdul[0].header
    # Obtain the necessary info from the header
    targcoord = astropy.coordinates.SkyCoord(
        ra=pheader['PROP_RA'], dec=pheader['PROP_DEC'], frame='fk5', unit=(u.hourangle, u.deg))
    starttime = pheader['EXPSTART']
    middletime = pheader['EXPMID']
    endtime = pheader['EXPEND']
    times = astropy.time.Time(np.array([starttime, middletime, endtime]),
        format='mjd', scale='utc').tt.mjd
    ((bstrtime, bmidtime, bendtime), (hstrtime, hmidtime, hendtime)) = \
        timeconversion.compute_bary_helio_time(
            targetcoord=(targcoord.ra.degree, targcoord.dec.degree), times=times)
    pheader['BSTRTIME'] = bstrtime
    pheader['BMIDTIME'] = bmidtime
    pheader['BENDTIME'] = bendtime
    pheader['BARTDELT'] = (bstrtime - starttime) * 86400.
    pheader['HSTRTIME'] = hstrtime
    pheader['HMIDTIME'] = hmidtime
    pheader['HENDTIME'] = hendtime
    pheader['HELIDELT'] = (hstrtime - starttime) * 86400.
    # Now modify the table
    tabhdu = hdul['GROUP']
    tendtimes = tabhdu.data['group_end_time']
    # replace colon as separator between date and time to be consistent
    tendtimeslist = [item[:10] + 'T' + item[11:] for item in tendtimes]
    astropy_endtimes = astropy.time.Time(tendtimeslist, format='isot', scale='utc')
    mjdtimes = astropy_endtimes.tt.mjd
    try:
        btimes, htimes = timeconversion.compute_bary_helio_time(
            targetcoord=(targcoord.ra.degree, targcoord.dec.degree), times=mjdtimes)
    except Exception as exception:
        warnings.warn(
            'Error in calculating times. Filling with invalid dates.'
            '\nError is "{}"'.format(exception)
        )
        nulls = -1.0 * np.ones(len(tendtimeslist), dtype=np.float)
        bcol = fits.Column(name='bary_end_time', format='D', unit='MJD', array=nulls)
        hcol = fits.Column(name='helio_end_time', format='D', unit='MJD', array=nulls)
    else:
        bcol = fits.Column(name='bary_end_time', format='D', unit='MJD', array=btimes)
        hcol = fits.Column(name='helio_end_time', format='D', unit='MJD', array=htimes)
    binhdu = fits.BinTableHDU.from_columns(tabhdu.columns + fits.ColDefs([bcol, hcol]))
    binhdu.header['EXTNAME'] = 'GROUP'
    hdul['GROUP'] = binhdu
    hdul.flush()
    hdul.close()
    print('Completed set_bary_helio_times task')
예제 #2
0
def set_bary_helio_times(filename, jwstpos=None):
    '''
    Compute the barycentric and heliocentric times for the
    given file and update the contents of the file to contain 
    these values.
    '''
    print('Starting set_bary_helio_times task')
    hdul = fits.open(filename, mode='update')
    pheader = hdul[0].header
    # Obtain the necessary info from the header
    targcoord = astropy.coordinates.SkyCoord(
        ra=pheader['PROP_RA'], dec=pheader['PROP_DEC'], frame='fk5', unit=(u.hourangle,u.deg))
    starttime = pheader['EXPSTART']
    middletime = pheader['EXPMID']
    endtime = pheader['EXPEND']
    times = astropy.time.Time(np.array([starttime, middletime, endtime]),
        format='mjd', scale='utc').tt.mjd
    ((bstrtime, bmidtime, bendtime),(hstrtime, hmidtime, hendtime)) = \
        timeconversion.compute_bary_helio_time(
            targetcoord=(targcoord.ra.degree, targcoord.dec.degree), times=times)
    pheader['BSTRTIME'] = bstrtime
    pheader['BMIDTIME'] = bmidtime
    pheader['BENDTIME'] = bendtime
    pheader['BARTDELT'] = (bstrtime - starttime) * 86400.
    pheader['HSTRTIME'] = hstrtime
    pheader['HMIDTIME'] = hmidtime
    pheader['HENDTIME'] = hendtime
    pheader['HELIDELT'] = (hstrtime - starttime) * 86400.
    # Now modify the table
    tabhdu = hdul['GROUP']
    tendtimes = tabhdu.data['group_end_time']
    # replace colon as separator between date and time to be consistent
    tendtimeslist = [item[:10]+'T'+item[11:] for item in tendtimes]
    astropy_endtimes = astropy.time.Time(tendtimeslist, format='isot', scale='utc')
    mjdtimes = astropy_endtimes.tt.mjd
    btimes, htimes = timeconversion.compute_bary_helio_time(
        targetcoord=(targcoord.ra.degree, targcoord.dec.degree), times=mjdtimes)
    bcol = fits.Column(name='bary_end_time', format='D', unit='MJD', array=btimes)
    hcol = fits.Column(name='helio_end_time', format='D', unit='MJD', array=htimes)
    binhdu = fits.BinTableHDU.from_columns(tabhdu.columns + fits.ColDefs([bcol, hcol]))
    binhdu.header['EXTNAME'] = 'GROUP'
    hdul['GROUP'] = binhdu
    hdul.flush()
    hdul.close()
    print('Completed set_bary_helio_times task')
예제 #3
0
def utc_tdb(filename):
    """Convert start, mid, end times from UTC to TDB.

    Parameters
    ----------
    filename: str
        Name of an input FITS file containing an INT_TIMES table.

    Returns
    -------
    tuple of three numpy arrays
        The time or times, expressed as MJD and with time scale TDB.
    """

    log.info("Processing file %s", filename)
    fd = fits.open(filename, mode="update")

    targetcoord = (fd[0].header["targ_ra"], fd[0].header["targ_dec"])

    try:
        hdunum = find_hdu(fd, "int_times")
    except RuntimeError as e:
        log.warning(str(e))
        fd.close()
        return (0., 0., 0.)

    # TT, MJD
    tt_start_times = to_tt(fd[hdunum].data.field("int_start_MJD_UTC"))
    tt_mid_times = to_tt(fd[hdunum].data.field("int_mid_MJD_UTC"))
    tt_end_times = to_tt(fd[hdunum].data.field("int_end_MJD_UTC"))

    # Function compute_bary_helio_time returns both barycentric and
    # heliocentric times; the "[0]" extracts the former.
    if USE_TIMECONVERSION:
        log.debug("Using the timeconversion module.")
        tdb_start_times = timeconversion.compute_bary_helio_time(
            targetcoord, tt_start_times)[0]
        tdb_mid_times = timeconversion.compute_bary_helio_time(
            targetcoord, tt_mid_times)[0]
        tdb_end_times = timeconversion.compute_bary_helio_time(
            targetcoord, tt_end_times)[0]
    else:
        log.warning("Couldn't import the timeconversion module;")
        log.warning("using astropy.coordinates, and "
                    "JWST position and velocity keywords.")
        (eph_time, jwst_pos, jwst_vel) = get_jwst_keywords(fd)
        jwstpos = linear_pos(tt_start_times, eph_time, jwst_pos, jwst_vel)
        tdb_start_times = compute_bary_helio_time2(targetcoord, tt_start_times,
                                                   jwstpos)[0]
        jwstpos = linear_pos(tt_mid_times, eph_time, jwst_pos, jwst_vel)
        tdb_mid_times = compute_bary_helio_time2(targetcoord, tt_mid_times,
                                                 jwstpos)[0]
        jwstpos = linear_pos(tt_end_times, eph_time, jwst_pos, jwst_vel)
        tdb_end_times = compute_bary_helio_time2(targetcoord, tt_end_times,
                                                 jwstpos)[0]

    missing = False
    try:
        # TDB, MJD
        fd[hdunum].data.field("int_start_BJD_TDB")[:] = tdb_start_times.copy()
        fd[hdunum].data.field("int_mid_BJD_TDB")[:] = tdb_mid_times.copy()
        fd[hdunum].data.field("int_end_BJD_TDB")[:] = tdb_end_times.copy()
    except KeyError:
        missing = True

    fd.close()

    if missing:
        log.warning("One or more of the *BJD_TDB columns do not exist,")
        log.warning("so the INT_TIMES table was not updated.")

    return (tdb_start_times, tdb_mid_times, tdb_end_times)
예제 #4
0
def utc_tdb(filename, update_tdb=True, update_velosys=True,
            delta_t=1000., ndecimals=2):
    """Convert start, mid, end times from UTC to TDB.

    Parameters
    ----------
    filename: str
        Name of an input FITS file containing an INT_TIMES table.

    update_tdb: bool
        If True, the UTC times in the INT_TIMES table will be converted
        to TDB, and the three TDB columns in the INT_TIMES table will be
        updated with the computed values.

    update_velosys: bool
        If True, the radial velocity of JWST will be computed at the
        middle of the exposure, and the value in meters / second will
        be assigned to keyword VELOSYS in the first SCI extension.

    delta_t: float
        This is used only if `update_velosys` is True.  The TDB times
        corresponding to two UTC times (that are centered on the middle
        of the exposure and separated by `delta_t` seconds) will be
        computed, and the radial velocity will be computed from the
        difference between the two TDB times.

    ndecimals: int
        This is used only if `update_velosys` is True.  The radial
        velocity will be rounded to `ndecimals` decimal places.

    Returns
    -------
    tuple of three numpy arrays
        If `update_tdb` is True, the returned value will be the TDB time
        or times, expressed as MJD and with time scale TDB; otherwise,
        a tuple of three zeros (floats) will be returned.
    """

    if not update_tdb and not update_velosys:
        log.warning("Both update_tdb and update_velosys are False; "
                    "there's nothing to do.")
        return (0., 0., 0.)

    log.info("Processing file %s", filename)
    fd = fits.open(filename, mode="update")

    targetcoord = (fd[0].header["targ_ra"], fd[0].header["targ_dec"])

    if update_velosys:
        # Compute VELOSYS at the middle of the exposure.
        try:
            expmid = fd[0].header["expmid"]
            update_keyword = True
        except KeyError as e:
            log.warning(str(e))
            log.warning("Can't update VELOSYS without the time.")
            update_keyword = False

        if update_keyword:
            half_dt = delta_t / (86400. * 2.)       # and convert to days
            tt_rv_times = np.array([to_tt(expmid - half_dt),
                                    to_tt(expmid + half_dt)])
            if USE_TIMECONVERSION:
                tdb_rv_times = timeconversion.compute_bary_helio_time(
                                    targetcoord, tt_rv_times)[0]
            else:
                (eph_time, jwst_pos, jwst_vel) = get_jwst_keywords(fd)
                jwstpos_rv = linear_pos(tt_rv_times, eph_time,
                                        jwst_pos, jwst_vel)
                tdb_rv_times = compute_bary_helio_time2(
                                    targetcoord, tt_rv_times, jwstpos_rv)[0]

            # This is almost exactly the same as delta_t, but in units of days.
            delta_tt = tt_rv_times[1] - tt_rv_times[0]
            # This will be close to delta_t (in days), but it can differ due to
            # the motion of the earth along the line of sight to or from the
            # target.
            delta_tdb = tdb_rv_times[1] - tdb_rv_times[0]
            time_diff = (delta_tt - delta_tdb) * 86400.     # seconds
            radial_velocity = time_diff * astropy.constants.c.value / delta_t
            radial_velocity = round(radial_velocity, ndecimals)
            log.info("radial velocity = {}".format(radial_velocity))

            scihdu = find_hdu(fd, "sci")
            fd[scihdu].header["velosys"] = \
                    (radial_velocity, "Radial velocity wrt barycenter [m / s]")

    if update_tdb:
        try:
            hdunum = find_hdu(fd, "int_times")
        except RuntimeError as e:
            log.warning(str(e))
            fd.close()
            return (0., 0., 0.)

        # TT, MJD
        tt_start_times = to_tt(fd[hdunum].data.field("int_start_MJD_UTC"))
        tt_mid_times = to_tt(fd[hdunum].data.field("int_mid_MJD_UTC"))
        tt_end_times = to_tt(fd[hdunum].data.field("int_end_MJD_UTC"))

        # Function compute_bary_helio_time returns both barycentric and
        # heliocentric times; the "[0]" extracts the former.
        if USE_TIMECONVERSION:
            log.debug("Using the timeconversion module.")
            tdb_start_times = timeconversion.compute_bary_helio_time(
                                    targetcoord, tt_start_times)[0]
            tdb_mid_times = timeconversion.compute_bary_helio_time(
                                    targetcoord, tt_mid_times)[0]
            tdb_end_times = timeconversion.compute_bary_helio_time(
                                    targetcoord, tt_end_times)[0]
        else:
            log.warning("Couldn't import the timeconversion module;")
            log.warning("using astropy.coordinates, and "
                        "JWST position and velocity keywords.")
            (eph_time, jwst_pos, jwst_vel) = get_jwst_keywords(fd)
            jwstpos = linear_pos(tt_start_times, eph_time, jwst_pos, jwst_vel)
            tdb_start_times = compute_bary_helio_time2(
                                    targetcoord, tt_start_times, jwstpos)[0]
            jwstpos = linear_pos(tt_mid_times, eph_time, jwst_pos, jwst_vel)
            tdb_mid_times = compute_bary_helio_time2(
                                    targetcoord, tt_mid_times, jwstpos)[0]
            jwstpos = linear_pos(tt_end_times, eph_time, jwst_pos, jwst_vel)
            tdb_end_times = compute_bary_helio_time2(
                                    targetcoord, tt_end_times, jwstpos)[0]

        try:
            # TDB, MJD
            fd[hdunum].data.field("int_start_BJD_TDB")[:] = \
                        tdb_start_times.copy()
            fd[hdunum].data.field("int_mid_BJD_TDB")[:] = tdb_mid_times.copy()
            fd[hdunum].data.field("int_end_BJD_TDB")[:] = tdb_end_times.copy()
        except KeyError:
            log.warning("One or more of the *BJD_TDB columns do not exist,")
            log.warning("so the INT_TIMES table was not updated.")
    else:
        (tdb_start_times, tdb_mid_times, tdb_end_times) = (0., 0., 0.)

    fd.close()

    return (tdb_start_times, tdb_mid_times, tdb_end_times)
예제 #5
0
def set_bary_helio_times(filename, jwstpos=None):
    '''
    Compute the barycentric and heliocentric times for the
    given file and update the contents of the file to contain
    these values.
    '''
    logging.info('Starting set_bary_helio_times task')
    hdul = fits.open(filename, mode='update')
    pheader = hdul[0].header
    # Obtain the necessary info from the header
    targcoord = astropy.coordinates.SkyCoord(
        ra=pheader['TARG_RA'],
        dec=pheader['TARG_DEC'],
        frame='fk5',
        unit=(u.hourangle, u.deg)
    )
    starttime = pheader['EXPSTART']
    middletime = pheader['EXPMID']
    endtime = pheader['EXPEND']
    times = astropy.time.Time(
        np.array([starttime, middletime, endtime]),
        format='mjd', scale='utc').tt.mjd
    ((bstrtime, bmidtime, bendtime), (hstrtime, hmidtime, hendtime)) = \
        timeconversion.compute_bary_helio_time(
            targetcoord=(targcoord.ra.degree, targcoord.dec.degree),
            times=times
        )
    pheader['BSTRTIME'] = bstrtime
    pheader['BMIDTIME'] = bmidtime
    pheader['BENDTIME'] = bendtime
    pheader['BARTDELT'] = (bstrtime - starttime) * 86400.
    pheader['HSTRTIME'] = hstrtime
    pheader['HMIDTIME'] = hmidtime
    pheader['HENDTIME'] = hendtime
    pheader['HELIDELT'] = (hstrtime - starttime) * 86400.

    # Now modify the table
    try:
        tabhdu = hdul['GROUP']
    except KeyError:
        logging.info('No GROUP extension found. Ignoring GROUP calculations')
        pass
    else:
        logging.info('Calculating GROUP times')
        tendtimes = tabhdu.data['group_end_time']

        # replace colon as separator between date and time to be consistent
        tendtimeslist = [item[:10] + 'T' + item[11:] for item in tendtimes]
        astropy_endtimes = astropy.time.Time(
            tendtimeslist, format='isot', scale='utc'
        )
        mjdtimes = astropy_endtimes.tt.mjd
        try:
            btimes, htimes = timeconversion.compute_bary_helio_time(
                targetcoord=(targcoord.ra.degree, targcoord.dec.degree),
                times=mjdtimes
            )
        except Exception as exception:
            logging.warning(
                'Error in calculating times. Filling with invalid dates.'
                '\nError is "{}"'.format(exception)
            )
            nulls = -1.0 * np.ones(len(tendtimeslist), dtype=np.float)
            bcol = fits.Column(
                name='bary_end_time', format='D', unit='MJD', array=nulls
            )
            hcol = fits.Column(
                name='helio_end_time', format='D', unit='MJD', array=nulls
            )
        else:
            bcol = fits.Column(
                name='bary_end_time', format='D', unit='MJD', array=btimes
            )
            hcol = fits.Column(
                name='helio_end_time', format='D', unit='MJD', array=htimes
            )
        binhdu = fits.BinTableHDU.from_columns(
            tabhdu.columns + fits.ColDefs([bcol, hcol])
        )
        binhdu.header['EXTNAME'] = 'GROUP'
        hdul['GROUP'] = binhdu

    hdul.flush()
    hdul.close()
    logging.info('Completed set_bary_helio_times task')
예제 #6
0
def utc_tdb(filename, update_tdb=True, update_velosys=True,
            delta_t=1000., ndecimals=2):
    """Convert start, mid, end times from UTC to TDB.

    Parameters
    ----------
    filename: str
        Name of an input FITS file containing an INT_TIMES table.

    update_tdb: bool
        If True, the UTC times in the INT_TIMES table will be converted
        to TDB, and the three TDB columns in the INT_TIMES table will be
        updated with the computed values.

    update_velosys: bool
        If True, the radial velocity of JWST will be computed at the
        middle of the exposure, and the value in meters / second will
        be assigned to keyword VELOSYS in the first SCI extension.

    delta_t: float
        This is used only if `update_velosys` is True.  The TDB times
        corresponding to two UTC times (that are centered on the middle
        of the exposure and separated by `delta_t` seconds) will be
        computed, and the radial velocity will be computed from the
        difference between the two TDB times.

    ndecimals: int
        This is used only if `update_velosys` is True.  The radial
        velocity will be rounded to `ndecimals` decimal places.

    Returns
    -------
    tuple of three numpy arrays
        If `update_tdb` is True, the returned value will be the TDB time
        or times, expressed as MJD and with time scale TDB; otherwise,
        a tuple of three zeros (floats) will be returned.
    """

    if not update_tdb and not update_velosys:
        log.warning("Both update_tdb and update_velosys are False; "
                    "there's nothing to do.")
        return (0., 0., 0.)

    log.info("Processing file %s", filename)
    fd = fits.open(filename, mode="update")

    targetcoord = (fd[0].header["targ_ra"], fd[0].header["targ_dec"])

    if update_velosys:
        # Compute VELOSYS at the middle of the exposure.
        try:
            expmid = fd[0].header["expmid"]
            update_keyword = True
        except KeyError as e:
            log.warning(str(e))
            log.warning("Can't update VELOSYS without the time.")
            update_keyword = False

        if update_keyword:
            half_dt = delta_t / (86400. * 2.)       # and convert to days
            tt_rv_times = np.array([to_tt(expmid - half_dt),
                                    to_tt(expmid + half_dt)])
            if USE_TIMECONVERSION:
                tdb_rv_times = timeconversion.compute_bary_helio_time(
                    targetcoord, tt_rv_times)[0]
            else:
                (eph_time, jwst_pos, jwst_vel) = get_jwst_keywords(fd)
                jwstpos_rv = linear_pos(tt_rv_times, eph_time,
                                        jwst_pos, jwst_vel)
                tdb_rv_times = compute_bary_helio_time2(
                    targetcoord, tt_rv_times, jwstpos_rv)[0]

            # This is almost exactly the same as delta_t, but in units of days.
            delta_tt = tt_rv_times[1] - tt_rv_times[0]
            # This will be close to delta_t (in days), but it can differ due to
            # the motion of the earth along the line of sight to or from the
            # target.
            delta_tdb = tdb_rv_times[1] - tdb_rv_times[0]
            time_diff = (delta_tt - delta_tdb) * 86400.     # seconds
            radial_velocity = time_diff * astropy.constants.c.value / delta_t
            radial_velocity = round(radial_velocity, ndecimals)
            log.info("radial velocity = {}".format(radial_velocity))

            scihdu = find_hdu(fd, "sci")
            fd[scihdu].header["velosys"] = \
                (radial_velocity, "Radial velocity wrt barycenter [m / s]")

    if update_tdb:
        try:
            hdunum = find_hdu(fd, "int_times")
        except RuntimeError as e:
            log.warning(str(e))
            fd.close()
            return (0., 0., 0.)

        # TT, MJD
        tt_start_times = to_tt(fd[hdunum].data.field("int_start_MJD_UTC"))
        tt_mid_times = to_tt(fd[hdunum].data.field("int_mid_MJD_UTC"))
        tt_end_times = to_tt(fd[hdunum].data.field("int_end_MJD_UTC"))

        # Function compute_bary_helio_time returns both barycentric and
        # heliocentric times; the "[0]" extracts the former.
        if USE_TIMECONVERSION:
            log.debug("Using the timeconversion module.")
            tdb_start_times = timeconversion.compute_bary_helio_time(
                targetcoord, tt_start_times)[0]
            tdb_mid_times = timeconversion.compute_bary_helio_time(
                targetcoord, tt_mid_times)[0]
            tdb_end_times = timeconversion.compute_bary_helio_time(
                targetcoord, tt_end_times)[0]
        else:
            log.warning("Couldn't import the timeconversion module;")
            log.warning("using astropy.coordinates, and "
                        "JWST position and velocity keywords.")
            (eph_time, jwst_pos, jwst_vel) = get_jwst_keywords(fd)
            jwstpos = linear_pos(tt_start_times, eph_time, jwst_pos, jwst_vel)
            tdb_start_times = compute_bary_helio_time2(
                targetcoord, tt_start_times, jwstpos)[0]
            jwstpos = linear_pos(tt_mid_times, eph_time, jwst_pos, jwst_vel)
            tdb_mid_times = compute_bary_helio_time2(
                targetcoord, tt_mid_times, jwstpos)[0]
            jwstpos = linear_pos(tt_end_times, eph_time, jwst_pos, jwst_vel)
            tdb_end_times = compute_bary_helio_time2(
                targetcoord, tt_end_times, jwstpos)[0]

        try:
            # TDB, MJD
            fd[hdunum].data.field("int_start_BJD_TDB")[:] = \
                tdb_start_times.copy()
            fd[hdunum].data.field("int_mid_BJD_TDB")[:] = tdb_mid_times.copy()
            fd[hdunum].data.field("int_end_BJD_TDB")[:] = tdb_end_times.copy()
        except KeyError:
            log.warning("One or more of the *BJD_TDB columns do not exist,")
            log.warning("so the INT_TIMES table was not updated.")
    else:
        (tdb_start_times, tdb_mid_times, tdb_end_times) = (0., 0., 0.)

    fd.close()

    return (tdb_start_times, tdb_mid_times, tdb_end_times)