def test_plot_image_data_change(): """Test that the plotting function does not change input data""" # Construct random image: img = np.random.randn(15, 10) img[0, 0] = -1.0 # Make 100% sure there is a negative point # Save the original image for comparison: img_before = np.copy(img) # Make a couple of plots trying out the different settings: fig = plt.figure() ax1 = fig.add_subplot(131) plot_image(img, ax=ax1, scale='linear') np.testing.assert_allclose(img, img_before) ax2 = fig.add_subplot(132) plot_image(img, ax=ax2, scale='sqrt') np.testing.assert_allclose(img, img_before) ax3 = fig.add_subplot(133) plot_image(img, ax=ax3, scale='log') np.testing.assert_allclose(img, img_before) fig = plt.figure() plot_image_fit_residuals(fig, img, img, img) np.testing.assert_allclose(img, img_before)
def test_aperturephotometry(): INPUT_DIR = os.path.join(os.path.dirname(__file__), 'input') OUTPUT_DIR = tempfile.mkdtemp(prefix='tessphot_tests_aperture') for datasource in ('tpf', 'ffi'): with AperturePhotometry(182092046, INPUT_DIR, OUTPUT_DIR, plot=True, datasource=datasource, camera=1, ccd=1) as pho: pho.photometry() pho.save_lightcurve() print( pho.lightcurve ) # It should set the status to one of these: assert(pho.status in (STATUS.OK, STATUS.WARNING)) plt.figure() plot_image(pho.sumimage, title=datasource) plt.show() # They shouldn't be exactly zero: assert( ~np.all(pho.lightcurve['flux'] == 0) ) assert( ~np.all(pho.lightcurve['pos_centroid'][:,0] == 0) ) assert( ~np.all(pho.lightcurve['pos_centroid'][:,1] == 0) ) # They shouldn't be NaN (in this case!): assert( ~np.all(np.isnan(pho.lightcurve['flux'])) ) assert( ~np.all(np.isnan(pho.lightcurve['pos_centroid'][:,0])) ) assert( ~np.all(np.isnan(pho.lightcurve['pos_centroid'][:,1])) )
def test_aperturephotometry(): with TemporaryDirectory() as OUTPUT_DIR: for datasource in ('tpf', 'ffi'): with AperturePhotometry(DUMMY_TARGET, INPUT_DIR, OUTPUT_DIR, plot=True, datasource=datasource, **DUMMY_KWARG) as pho: pho.photometry() pho.save_lightcurve() print(pho.lightcurve) # It should set the status to one of these: assert (pho.status in (STATUS.OK, STATUS.WARNING)) plt.figure() plot_image(pho.sumimage, title=datasource) plt.show() # They shouldn't be exactly zero: assert (~np.all(pho.lightcurve['flux'] == 0)) assert (~np.all(pho.lightcurve['pos_centroid'][:, 0] == 0)) assert (~np.all(pho.lightcurve['pos_centroid'][:, 1] == 0)) # They shouldn't be NaN (in this case!): assert (~np.all(np.isnan(pho.lightcurve['flux']))) assert ( ~np.all(np.isnan(pho.lightcurve['pos_centroid'][:, 0]))) assert ( ~np.all(np.isnan(pho.lightcurve['pos_centroid'][:, 1])))
def test_aperturephotometry(SHARED_INPUT_DIR, datasource): with TemporaryDirectory() as OUTPUT_DIR: with AperturePhotometry(DUMMY_TARGET, SHARED_INPUT_DIR, OUTPUT_DIR, plot=True, datasource=datasource, **DUMMY_KWARG) as pho: pho.photometry() filepath = pho.save_lightcurve() print(pho.lightcurve) # It should set the status to one of these: assert (pho.status in (STATUS.OK, STATUS.WARNING)) # Check the sumimage: plt.figure() plot_image(pho.sumimage, title=datasource) assert not anynan(pho.sumimage), "There are NaNs in the SUMIMAGE" # They shouldn't be exactly zero: assert not np.all(pho.lightcurve['flux'] == 0) assert not np.all(pho.lightcurve['flux_err'] == 0) assert not np.all(pho.lightcurve['pos_centroid'][:, 0] == 0) assert not np.all(pho.lightcurve['pos_centroid'][:, 1] == 0) # They shouldn't be NaN (in this case!): assert not allnan(pho.lightcurve['flux']) assert not allnan(pho.lightcurve['flux_err']) assert not allnan(pho.lightcurve['pos_centroid'][:, 0]) assert not allnan(pho.lightcurve['pos_centroid'][:, 1]) assert not np.any(~np.isfinite(pho.lightcurve['time'])) assert not np.any(pho.lightcurve['time'] == 0) # Test the outputted FITS file: with fits.open(filepath, mode='readonly') as hdu: # Should be the same vectors in FITS as returned in Table: np.testing.assert_allclose(pho.lightcurve['time'], hdu[1].data['TIME']) np.testing.assert_allclose(pho.lightcurve['timecorr'], hdu[1].data['TIMECORR']) np.testing.assert_allclose(pho.lightcurve['flux'], hdu[1].data['FLUX_RAW']) np.testing.assert_allclose(pho.lightcurve['flux_err'], hdu[1].data['FLUX_RAW_ERR']) np.testing.assert_allclose(pho.lightcurve['cadenceno'], hdu[1].data['CADENCENO']) # Test FITS aperture image: ap = hdu['APERTURE'].data print(ap) assert np.all(pho.aperture == ap), "Aperture image mismatch" assert not anynan(ap), "NaN in aperture image" assert np.all(ap >= 0), "Negative values in aperture image" assert np.any(ap & 2 != 0), "No photometric mask set" assert np.any(ap & 8 != 0), "No position mask set"
def test_position_velocity(keep_figures=False): with TESS_SPICE() as knl: # We should be able to load and close without affecting the results of the following: with TESS_SPICE(): pass time_nocorr = np.array( [1325.32351727, 1325.34435059, 1325.36518392, 1325.38601724]) # Get the location of TESS as a function of time relative to Earth in kilometers: pos = knl.position(time_nocorr + 2457000) assert pos.shape == (len(time_nocorr), 3) # Get the location of TESS as a function of time relative to Earth in kilometers: vel = knl.velocity(time_nocorr + 2457000) assert vel.shape == (len(time_nocorr), 3) # Plot TESS orbits in 3D: time_inter = np.linspace(time_nocorr[0] - 3, time_nocorr[-1] + 3, 2000) pos_inter = knl.position(time_inter + 2457000) vel_inter = knl.velocity(time_inter + 2457000) fig1 = plt.figure() ax = fig1.add_subplot(111, projection='3d') ax.plot(pos_inter[:, 0], pos_inter[:, 1], pos_inter[:, 2], 'r-') ax.scatter(pos[:, 0], pos[:, 1], pos[:, 2], alpha=0.5) ax.scatter(0, 0, 0, alpha=0.5, c='b') fig2 = plt.figure() ax1 = fig2.add_subplot(211) ax1.plot(time_inter, np.linalg.norm(pos_inter, axis=1), 'r-') ax1.scatter(time_nocorr, np.linalg.norm(pos, axis=1), alpha=0.5) ax1.set_ylabel('Distance (km)') ax1.set_xticks([]) ax2 = fig2.add_subplot(212) ax2.plot(time_inter, np.linalg.norm(vel_inter, axis=1), 'r-') ax2.scatter(time_nocorr, np.linalg.norm(vel, axis=1), alpha=0.5) ax2.set_ylabel('Velocity (km/s)') ax2.set_xlabel('Time') plt.tight_layout() if not keep_figures: plt.close(fig1) plt.close(fig2)
def test_plot_image_grid_offset(): img = np.zeros((5, 7)) img[:, 0] = 1 img[0, :] = 1 img[:, -1] = 1 img[-1, :] = 1 fig = plt.figure() ax = fig.add_subplot(111) plot_image(img, ax=ax, scale='linear', offset_axes=(3, 2)) ax.plot(3.5, 2.5, 'r+') ax.plot(8.5, 5.5, 'g+') ax.grid(True) return fig
def test_plot_image_grid(): img = np.zeros((5, 7)) img[:, 0] = 1 img[0, :] = 1 img[:, -1] = 1 img[-1, :] = 1 fig = plt.figure() ax = fig.add_subplot(111) plot_image(img, ax=ax, scale='linear') ax.plot(0.5, 0.5, 'r+') ax.plot(5.5, 3.5, 'g+') ax.grid(True) return fig
def test_plot_image(): mu = [3.5, 3] x, y = np.mgrid[0:10, 0:10] pos = np.dstack((x, y)) var = scipy.stats.multivariate_normal(mean=mu, cov=[[1, 0], [0, 1]]) gauss = var.pdf(pos) fig = plt.figure(figsize=(12, 6)) ax1 = fig.add_subplot(131) plot_image(gauss, ax=ax1, scale='linear', title='Linear') ax1.plot(mu[1], mu[0], 'r+') ax2 = fig.add_subplot(132) plot_image(gauss, ax=ax2, scale='sqrt', title='Sqrt') ax2.plot(mu[1], mu[0], 'r+') ax3 = fig.add_subplot(133) plot_image(gauss, ax=ax3, scale='log', title='Log') ax3.plot(mu[1], mu[0], 'r+') return fig
def test_spice(SHARED_INPUT_DIR, starid): # Initialize our home-made TESS Kernel object: with TESS_SPICE() as knl: print("="*72) print("TIC %d" % starid) tpf_file = find_tpf_files(SHARED_INPUT_DIR, starid=starid)[0] with fits.open(tpf_file, mode='readonly', memmap=True) as hdu: time_tpf = hdu[1].data['TIME'] timecorr_tpf = hdu[1].data['TIMECORR'] camera = hdu[0].header['CAMERA'] ccd = hdu[0].header['CCD'] # Coordinates of the target as astropy SkyCoord object: star_coord = coord.SkyCoord( ra=hdu[0].header['RA_OBJ'], dec=hdu[0].header['DEC_OBJ'], unit=u.deg, frame='icrs', obstime=Time('J2000'), pm_ra_cosdec=hdu[0].header['PMRA']*u.mas/u.yr, pm_dec=hdu[0].header['PMDEC']*u.mas/u.yr, radial_velocity=0*u.km/u.s ) # Load the original timestamps from FFIs: hdf_file = find_hdf5_files(SHARED_INPUT_DIR, camera=camera, ccd=ccd)[0] with h5py.File(hdf_file, 'r') as hdf: ffi_time = np.asarray(hdf['time']) ffi_timecorr = np.asarray(hdf['timecorr']) f = interp1d(time_tpf-timecorr_tpf, timecorr_tpf, kind='linear') # Change the timestamps bach to JD: time_nocorr = ffi_time - ffi_timecorr times = Time(time_nocorr, 2457000, format='jd', scale='tdb') ras, decs = add_proper_motion( star_coord.ra.value, star_coord.dec.value, star_coord.pm_ra_cosdec.value, star_coord.pm_dec.value, times.jd ) star_coord = coord.SkyCoord( ra=ras[0], dec=decs[0], unit=u.deg, frame='icrs' ) print(star_coord) # Use Greenwich as location instead of TESS (similar to what is done in Elenor): greenwich = coord.EarthLocation.of_site('greenwich') times_greenwich = Time(time_nocorr+2457000, format='jd', scale='utc', location=greenwich) timecorr_greenwich = times_greenwich.light_travel_time(star_coord, kind='barycentric', ephemeris='builtin').value #time_greenwich = time_nocorr + timecorr_greenwich # Calculate barycentric correction using our method: time_astropy, timecorr_astropy = knl.barycorr(time_nocorr + 2457000, star_coord) # Calculate barycentric correction using second method: timecorr_knl = knl.barycorr2(time_nocorr + 2457000, star_coord) print(timecorr_knl) # Plot the new barycentric time correction and the old one: fig1 = plt.figure() ax = fig1.add_subplot(111) ax.plot(time_tpf - timecorr_tpf, timecorr_tpf*86400, 'g.-', label='TPF timecorr') ax.plot(time_nocorr, ffi_timecorr*86400, 'b.-', label='FFI centre') ax.scatter(time_nocorr, timecorr_greenwich*86400, marker='x', label='Elenor timecorr') ax.scatter(time_nocorr, timecorr_astropy*86400, marker='x', c='r', label='Our timecorr') ax.set_xlabel('Uncorrected Time [TJD]') ax.set_ylabel('Barycentric Time Correction [s]') ax.set_title('TIC %d' % starid) ax.set_yscale('log') plt.legend() # Plot the new barycentric time correction and the old one: fig2 = plt.figure(figsize=(8,10)) ax3 = fig2.add_subplot(111) ax3.axhline(1.0, color='k', ls='--', lw=1) ax3.plot(time_nocorr, np.abs(ffi_timecorr - f(time_nocorr))*86400, '.-', label='FFI centre') ax3.plot(time_nocorr, np.abs(timecorr_greenwich - f(time_nocorr))*86400*1000, '.-', label='Elenor') ax3.plot(time_nocorr, np.abs(timecorr_astropy - f(time_nocorr))*86400*1000, '.-', label='Astropy') ax3.plot(time_nocorr, np.abs(timecorr_knl - f(time_nocorr))*86400*1000, '.-', label='Kernel') ax3.set_ylabel('abs(TimeCorr - TPF TimeCorr) [ms]') ax3.set_xlabel('Uncorrected Time [TJD]') ax3.set_yscale('log') ax3.set_ylim(bottom=0.1) ax3.legend() ax3.grid(axis='y', which='both', color='0.7', ls=':', lw=0.5) ax3.set_title('TIC %d' % starid) plt.tight_layout() assert np.all(86400000*np.abs(timecorr_astropy - f(time_nocorr)) < 1), "AstroPy method: More than 1 ms away" assert np.all(86400000*np.abs(timecorr_knl - f(time_nocorr)) < 1), "HomeMade method: More than 1 ms away" print("="*72)
def test_spice(keep_figures=False): # Initialize our home-made TESS Kernel object: with TESS_SPICE() as knl: for starid in (260795451, 267211065): print("=" * 72) print("TIC %d" % starid) tpf_file = find_tpf_files(INPUT_DIR, starid=starid)[0] with fits.open(tpf_file, mode='readonly', memmap=True) as hdu: time_tpf = hdu[1].data['TIME'] timecorr_tpf = hdu[1].data['TIMECORR'] camera = hdu[0].header['CAMERA'] ccd = hdu[0].header['CCD'] # Coordinates of the target as astropy SkyCoord object: star_coord = coord.SkyCoord( ra=hdu[0].header['RA_OBJ'], dec=hdu[0].header['DEC_OBJ'], unit=u.deg, frame='icrs', obstime=Time('J2000'), pm_ra_cosdec=hdu[0].header['PMRA'] * u.mas / u.yr, pm_dec=hdu[0].header['PMDEC'] * u.mas / u.yr, radial_velocity=0 * u.km / u.s) # Load the original timestamps from FFIs: hdf_file = find_hdf5_files(INPUT_DIR, camera=camera, ccd=ccd)[0] with h5py.File(hdf_file, 'r') as hdf: ffi_time = np.asarray(hdf['time']) ffi_timecorr = np.asarray(hdf['timecorr']) f = interp1d(time_tpf - timecorr_tpf, timecorr_tpf, kind='linear') # Change the timestamps bach to JD: time_nocorr = ffi_time - ffi_timecorr times = Time(time_nocorr, 2457000, format='jd', scale='tdb') ras, decs = add_proper_motion(star_coord.ra.value, star_coord.dec.value, star_coord.pm_ra_cosdec.value, star_coord.pm_dec.value, times.jd) star_coord = coord.SkyCoord(ra=ras[0], dec=decs[0], unit=u.deg, frame='icrs') print(star_coord) # Use Greenwich as location instead of TESS (similar to what is done in Elenor): greenwich = coord.EarthLocation.of_site('greenwich') times_greenwich = Time(time_nocorr + 2457000, format='jd', scale='utc', location=greenwich) timecorr_greenwich = times_greenwich.light_travel_time( star_coord, kind='barycentric', ephemeris='builtin').value #time_greenwich = time_nocorr + timecorr_greenwich # Calculate barycentric correction using our method: time_astropy, timecorr_astropy = knl.barycorr( time_nocorr + 2457000, star_coord) # Caluclate barycentric correction uning second method: timecorr_knl = knl.barycorr2(time_nocorr + 2457000, star_coord) print(timecorr_knl) # Plot the new barycentric time correction and the old one: fig1 = plt.figure() ax = fig1.add_subplot(111) ax.scatter(time_nocorr, ffi_timecorr * 86400, alpha=0.3, s=4, label='FFI timecorr') ax.scatter(time_tpf - timecorr_tpf, timecorr_tpf * 86400, alpha=0.3, s=4, label='TPF timecorr') ax.scatter(time_nocorr, timecorr_greenwich * 86400, alpha=0.3, s=4, label='Elenor timecorr') ax.scatter(time_nocorr, timecorr_astropy * 86400, alpha=0.3, s=4, label='Our timecorr') ax.set_xlabel('Uncorrected Time (JD - 2457000)') ax.set_ylabel('Barycentric Time Correction (s)') ax.set_title('TIC %d' % starid) plt.legend() # Plot the new barycentric time correction and the old one: fig2 = plt.figure(figsize=(8, 10)) ax1 = fig2.add_subplot(311) ax1.axhline(0, color='k', ls=':', lw=0.5) ax1.plot(time_nocorr, (ffi_timecorr - f(time_nocorr)) * 86400, '.') ax1.set_ylabel('FFI - TPF (seconds)') ax1.set_title('TIC %d' % starid) ax2 = fig2.add_subplot(312) ax2.axhline(0, color='k', ls=':', lw=0.5) ax2.plot(time_nocorr, (timecorr_greenwich - f(time_nocorr)) * 86400 * 1000, '.') ax2.set_ylabel('Elenor - TPF (ms)') ax3 = plt.subplot(313) ax3.axhline(0, color='k', ls=':', lw=0.5) ax3.plot(time_nocorr, (timecorr_astropy - f(time_nocorr)) * 86400 * 1000, '.', label='Astropy') ax3.plot(time_nocorr, (timecorr_knl - f(time_nocorr)) * 86400 * 1000, '.', label='Kernel') ax3.set_ylabel('Our - TPF (ms)') ax3.set_xlabel('Uncorrected Time (TJD)') ax3.legend() ax1.set_xticks([]) ax2.set_xticks([]) plt.tight_layout() if not keep_figures: plt.close(fig1) plt.close(fig2) print("=" * 72)
from photometry.plots import plt, plot_image, matplotlib from photometry.spice import TESS_SPICE from photometry.utilities import find_tpf_files, find_hdf5_files, add_proper_motion matplotlib.rcParams['font.family'] = 'serif' matplotlib.rcParams['font.size'] = '14' matplotlib.rcParams['axes.titlesize'] = '18' matplotlib.rcParams['axes.labelsize'] = '16' plt.rc('text', usetex=True) if __name__ == '__main__': plt.switch_backend('Qt5Agg') plt.close('all') INPUT_DIR = r'F:\tess_data\S06_DR08' fig4 = plt.figure() ax = fig4.add_subplot(111) ax.axhline(0, color='k', ls='--') for starid in (59545062, 25155664, 14003429): # Initialize our home-made TESS Kernel object: with TESS_SPICE() as knl: print("=" * 72) print("TIC %d" % starid) tpf_file = find_tpf_files(INPUT_DIR, starid=starid)[0] with fits.open(tpf_file, mode='readonly', memmap=True) as hdu: time_tpf = hdu[1].data['TIME'] timecorr_tpf = hdu[1].data['TIMECORR'] camera = hdu[0].header['CAMERA']