def getTessCut(self): """ Perform tesscut. Not Done, come back. """ manifest = Tesscut.get_cutouts(self.coord, size)
def get_ffi_image(target, cutout_deg=0.1): ra = target['ra'] dec = target['dec'] coord = SkyCoord(ra, dec, unit="deg") print(coord) npixels = 2 * np.ceil( cutout_deg * 3600 / 21) + 4 #This assumes 21arcsecond pixels) if npixels > 60: npixels = 60 print("Warning: cutout size set to 80 pixels.") if npixels < 10: npixels = 10 sector_tab = Tesscut.get_sectors(coordinates=coord) try: hdulist = Tesscut.get_cutouts(coord, size=npixels, sector=sector_tab[0]['sector']) except: print("Cutout not available") return [[0][0]], "no wcs" hdu = hdulist[0] aveImage = (hdu[1].data['FLUX'][0] + hdu[1].data['FLUX'][1] + hdu[1].data['FLUX'][2]) / 3 wcs = WCS(hdu[2].header) return aveImage, wcs
def __init__(self, ID: int, sectors: np.ndarray, search_radius: int = 10): """ Queries TIC for sources near the target and obtains a cutout of the pixels enclosing the target. Args: ID (int): TIC ID of the target. sectors (numpy array): Sectors in which the target has been observed. search_radius (int): Number of pixels from the target star to search. """ self.ID = ID self.sectors = sectors self.search_radius = search_radius self.N_pix = 2 * search_radius + 2 # query TIC for nearby stars pixel_size = 20.25 * u.arcsec df = Catalogs.query_object("TIC" + str(ID), radius=search_radius * pixel_size, catalog="TIC") new_df = df["ID", "Tmag", "ra", "dec", "mass", "rad", "Teff", "plx"] stars = new_df.to_pandas() self.stars = stars TESS_images = [] col0s, row0s = [], [] pix_coords = [] # for each sector, get FFI cutout and transform RA/Dec into # TESS pixel coordinates for j, sector in enumerate(sectors): Tmag = stars["Tmag"].values ra = stars["ra"].values dec = stars["dec"].values cutout_coord = SkyCoord(ra[0], dec[0], unit="deg") cutout_hdu = Tesscut.get_cutouts(cutout_coord, size=self.N_pix, sector=sector)[0] cutout_table = cutout_hdu[1].data hdu = cutout_hdu[2].header wcs = WCS(hdu) TESS_images.append(np.mean(cutout_table["FLUX"], axis=0)) col0 = cutout_hdu[1].header["1CRV4P"] row0 = cutout_hdu[1].header["2CRV4P"] col0s.append(col0) row0s.append(row0) pix_coord = np.zeros([len(ra), 2]) for i in range(len(ra)): RApix = np.asscalar(wcs.all_world2pix(ra[i], dec[i], 0)[0]) Decpix = np.asscalar(wcs.all_world2pix(ra[i], dec[i], 0)[1]) pix_coord[i, 0] = col0 + RApix pix_coord[i, 1] = row0 + Decpix pix_coords.append(pix_coord) self.TESS_images = TESS_images self.col0s = col0s self.row0s = row0s self.pix_coords = pix_coords return
def get_tess_cuts(coordinates, cube_side_size): """Gets the TESS cuts for a given set of coordinates, repeating on errors.""" cutouts = None while True: # This loop plus try is used to repeat if a connection error happens. try: cutouts = Tesscut.get_cutouts(coordinates, cube_side_size) break except HTTPError: print('HTTP error, trying again...') continue return cutouts
def getTessCutout(coord, size_pixels, sector): """ Returns first returned for that sector. """ hdulist = Tesscut.get_cutouts(coord, size_pixels, sector=sector) if len(hdulist) < 1: raise IOError hdu = hdulist[0] return hdu[1].data, hdu[1].header, hdu[2].header
def has_data(catalog, raname='ra', decname='dec', namename='Name', verbose=True, cutout=1): indices = [] for j, name in enumerate(catalog[namename]): ra, dec = catalog[j][raname, decname] coords = SkyCoord(ra, dec, unit=(u.hourangle, u.deg)) try: hdulist = Tesscut.get_cutouts( coords, cutout) # actually downloads the FITS files! eep! if len(hdulist) != 0: indices.append(j) if verbose: print('%s %.3f %.3f\n' % (name, coords.ra.deg, coords.dec.deg)) except: pass return indices
def get_multi_cutout_lst(coords, sz=(15, 15)): lst_hdu_elements = Tesscut.get_cutouts(coordinates=coords, size=sz) return (lst_hdu_elements)
def data_dl(ra, dec, size): cutout_coord = SkyCoord(ra, dec, unit="deg") hdulist = Tesscut.get_cutouts(coordinates=cutout_coord, size=size) return hdulist
def overplot_ticffi(targetlist, cutout_deg=.1, nearest=10): """ Plot tic positions on top of an ffi sector =0 means use the first available, otherwise use the specified sector. targetlist is a astropy table containing ID, ra, dec, Tmag The cutout will be performed around the first ra/dec """ ra = targetlist[0]['ra'] dec = targetlist[0]['dec'] coord = SkyCoord(ra, dec, unit="deg") npixels = 2 * np.ceil( cutout_deg * 3600 / 21) + 4 #This assumes 21arcsecond pixels) if npixels > 60: npixels = 60 print("Warning: cutout size set to 80 pixels.") if npixels < 10: npixels = 10 try: hdulist = Tesscut.get_cutouts(coord, size=npixels) except: print["Cutout not available"] return hdu = hdulist[0] firstImage = hdu[1].data['FLUX'][0] wcs = WCS(hdu[2].header) fig = plt.figure(figsize=(6, 6)) fig.add_subplot(111, projection=wcs) plot_cutout(firstImage) plt.xlabel('RA', fontsize=12) plt.ylabel('Dec', fontsize=12) starloc = wcs.all_world2pix([[ra, dec]], 0) #Second is origin plt.scatter(starloc[0, 0], starloc[0, 1], s=50, color='red') # Make it a list of Ra, Dec pairs of the bright ones. This is now a list of nearby bright stars. nearby_stars = list( map(lambda x, y: [x, y], targetlist['ra'], targetlist['dec'])) # Plot nearby stars as well, which we created using our Catalog call above. nearby_loc = wcs.all_world2pix(nearby_stars[1:nearest], 0) plt.scatter(nearby_loc[1:nearest, 0], nearby_loc[1:nearest, 1], s=27, color='orange') for i, v in enumerate(nearby_loc[:nearest]): r = np.random.rand() n = i + 1 #first is the target, not plotted here plt.annotate(str(n), (nearby_loc[i][0], nearby_loc[i][1]), textcoords="offset points", xytext=(-.1 + r, -.1 + r), ha='left', color='orange', fontsize=17) plt.title("TIC " + str(targetlist[0]['ID'])) return firstImage, wcs, fig
\*\* We must start by finding the sky coordinate of our star, however starting with the next Astroquery release, `Tesscut` functions will be able to take an object name such as a TIC ID as well. ''' # %% coord = Observations._resolve_object(f"TIC {tic_id}") # %% ''' **Requesting a cutout target pixel file. ** This query will return a list of `HDUList` objects, each of which is the cutout target pixel file for a single sector. In this case, because we specified a single sector we know that the resulting list will only have one element and can pull it out directly. ''' # %% cutout_hdu = Tesscut.get_cutouts(coordinates=coord, size=40, sector=1)[0] # %% cutout_hdu.info() # %% cutout_table = Table(cutout_hdu[1].data) cutout_table.columns # %% ''' #### Exploring the cutout time series We want to explore what is happening with in our cutout area over the time that the flare occurs, so we will make an animated plot of the cutout frames. We can't make a movie of the whole sector (it would take too long), so we will choose only the time range around the flare.
def measure_centroid(t0, per, dur, sector, sourceid, c_obj, outdir): """ Quoting Kostov+2019, who I followed: ''' 1) create the mean in-transit and out-of-transit images for each transit (ignoring cadences with non-zero quality flags), where the latter are based on the same number of exposure cadences as the former, split evenly before and after the transit; 2) calculate the overall mean in-transit and out-of-transit images by averaging over all transits; 3) subtract the overall mean out-of-transit image from the overall in-transit image to produce the overall mean difference image; and 4) measure the center-of-light for each difference and out-of-transit image by calculating the corresponding x- and y-moments of the image. The measured photocenters for the three planet candidates are shown in Figures 9, 10, and 11, and listed in Table 3. We detect no significant photocenter shifts between the respective difference images and out-of-transit images for any of the planet candidates, which confirms that the targets star is the source of the transits. ''' args: t0,per,dur : float, days. Epoch, period, duration. Used to isolate transit windows. sector (int) sourceid (int) c_obj (SkyCoord): location of target star returns: outdict = { 'm_oot_flux':m_oot_flux, # mean OOT image 'm_oot_flux_err':m_oot_flux_err, # mean OOT image uncert 'm_intra_flux':m_intra_flux, # mean in transit image 'm_intra_flux_err':m_intra_flux_err, # mean in transit image uncert 'm_oot_minus_intra_flux':m_oot_minus_intra_flux, # mean OOT - mean intra 'm_oot_minus_intra_flux_err':m_oot_minus_intra_flux_err, 'm_oot_minus_intra_snr':m_oot_minus_intra_snr, 'ctds_intra':ctds_intra, # centroids of all transits 'ctds_oot':ctds_oot, # centroids of all ootransits 'ctds_oot_minus_intra':ctds_oot_minus_intra, # centroids of diff 'm_ctd_intra':m_ctd_intra, # centroid of mean intransit image 'm_ctd_oot':m_ctd_oot, 'intra_imgs_flux':intra_imgs_flux, 'oot_imgs_flux':oot_imgs_flux, 'intra_imgs_flux_err':intra_imgs_flux_err, 'oot_imgs_flux_err':oot_imgs_flux_err } """ print('beginning tesscut for {}'.format(repr(c_obj))) try: cuthdul = Tesscut.get_cutouts(c_obj, size=10, sector=sector) except (requests.exceptions.HTTPError, requests.exceptions.ConnectionError) as e: print('got {}, try again'.format(repr(e))) pytime.sleep(30) try: cuthdul = Tesscut.get_cutouts(c_obj, size=10, sector=sector) except (requests.exceptions.HTTPError, requests.exceptions.ConnectionError) as e: print('ERR! sourceid {} FAILED TO GET TESSCUTOUT'.format(sourceid)) return None if len(cuthdul) != 1: print('ERR! sourceid {} GOT {} CUTOUTS'.format(sourceid, len(cuthdul))) return None else: cuthdul = cuthdul[0] data, data_hdr = cuthdul[1].data, cuthdul[1].header cutout_wcs = wcs.WCS(cuthdul[2].header) # flux and flux_err are image cubes of (time x spatial x spatial) quality = data['QUALITY'] flux = data['FLUX'] flux_err = data['FLUX_ERR'] time = data['TIME'] # in TJD time += 2457000 # now in BJD time = time[quality == 0] flux = flux[quality == 0] flux_err = flux_err[quality == 0] intra = transit_mask(time, per, dur, t0) mingap = per / 2 ngroups, groups = lcmath.find_lc_timegroups(time[intra], mingap=mingap) oot_times = time[~intra] # make mean in-transit and out-of-transit images & uncertainty maps for # each transit intra_imgs_flux, oot_imgs_flux = [], [] intra_imgs_flux_err, oot_imgs_flux_err = [], [] for group in groups: thistra_intra_time = time[intra][group] thistra_intra_flux = flux[intra][group] thistra_intra_flux_err = flux_err[intra][group] thistra_oot_time = _get_desired_oot_times(time, thistra_intra_time) thistra_oot_flux = flux[np.in1d(time, thistra_oot_time)] thistra_oot_flux_err = flux_err[np.in1d(time, thistra_oot_time)] intra_imgs_flux.append(np.mean(thistra_intra_flux, axis=0)) intra_imgs_flux_err.append(np.mean(thistra_intra_flux_err, axis=0)) oot_imgs_flux.append(np.mean(thistra_oot_flux, axis=0)) oot_imgs_flux_err.append(np.mean(thistra_oot_flux_err, axis=0)) # shapes: (n_transits, spatial, spatial) intra_imgs_flux = nparr(intra_imgs_flux) intra_imgs_flux_err = nparr(intra_imgs_flux_err) oot_imgs_flux = nparr(oot_imgs_flux) oot_imgs_flux_err = nparr(oot_imgs_flux_err) # average over transits, to get mean in-transit and out-of-transit images. m_intra_flux = np.mean(intra_imgs_flux, axis=0) m_intra_flux_err = np.mean(intra_imgs_flux_err, axis=0) m_oot_flux = np.mean(oot_imgs_flux, axis=0) m_oot_flux_err = np.mean(oot_imgs_flux_err, axis=0) # compute x and y centroid values for mean image m_ctd_intra = compute_centroid_from_first_moment(m_intra_flux) m_ctd_oot = compute_centroid_from_first_moment(m_oot_flux) ctd_m_oot_minus_m_intra = compute_centroid_from_first_moment(m_oot_flux - m_intra_flux) # compute x and y centroid values for each transit ctds_intra = nparr([ compute_centroid_from_first_moment(intra_imgs_flux[ix, :, :]) for ix in range(intra_imgs_flux.shape[0]) ]) ctds_oot = nparr([ compute_centroid_from_first_moment(oot_imgs_flux[ix, :, :]) for ix in range(oot_imgs_flux.shape[0]) ]) ctds_oot_minus_intra = nparr([ compute_centroid_from_first_moment(oot_imgs_flux[ix, :, :] - intra_imgs_flux[ix, :, :]) for ix in range(oot_imgs_flux.shape[0]) ]) # make OOT - intra image. NOTE: the uncertainty map might be a bit wrong, # b/c you should get a sqrt(N) on the flux in the mean image. I think. m_oot_minus_intra_flux = m_oot_flux - m_intra_flux m_oot_minus_intra_flux_err = np.sqrt(m_oot_flux_err**2 + m_intra_flux**2) m_oot_minus_intra_snr = m_oot_minus_intra_flux / m_oot_minus_intra_flux_err # calculate the centroid shift amplitude, deltaC = C_oot - C_intra delta_ctd_px = np.sqrt((m_ctd_oot[0] - m_ctd_intra[0])**2 + (m_ctd_oot[1] - m_ctd_intra[1])**2) delta_ctd_arcsec = delta_ctd_px * 21 # 21arcsec/px # error in centroid shift amplitude: assume it is roughly the scatter in # OOT centroids delta_ctd_err_px = np.sqrt( np.std(ctds_oot, axis=0)[0]**2 + np.std(ctds_oot, axis=0)[1]**2) delta_ctd_err_arcsec = delta_ctd_err_px * 21 outdict = { 'cutout_wcs': cutout_wcs, 'm_oot_flux': m_oot_flux, # mean OOT image 'm_oot_flux_err': m_oot_flux_err, # mean OOT image uncert 'm_intra_flux': m_intra_flux, # mean in transit image 'm_intra_flux_err': m_intra_flux_err, # mean in transit image uncert 'm_oot_minus_intra_flux': m_oot_minus_intra_flux, # mean OOT - mean intra 'm_oot_minus_intra_flux_err': m_oot_minus_intra_flux_err, 'm_oot_minus_intra_snr': m_oot_minus_intra_snr, 'ctds_intra': ctds_intra, # centroids of all transits 'ctds_oot': ctds_oot, # centroids of all ootransits 'ctds_oot_minus_intra': ctds_oot_minus_intra, 'm_ctd_intra': m_ctd_intra, # centroid of mean intransit image 'm_ctd_oot': m_ctd_oot, 'ctd_m_oot_minus_m_intra': ctd_m_oot_minus_m_intra, 'intra_imgs_flux': intra_imgs_flux, 'oot_imgs_flux': oot_imgs_flux, 'intra_imgs_flux_err': intra_imgs_flux_err, 'oot_imgs_flux_err': oot_imgs_flux_err, 'delta_ctd_arcsec': delta_ctd_arcsec, 'delta_ctd_err_arcsec': delta_ctd_err_arcsec, 'delta_ctd_sigma': delta_ctd_arcsec / delta_ctd_err_arcsec } outpath = os.path.join(outdir, '{}_ctds.pkl'.format(str(sourceid))) with open(outpath, 'wb') as f: pickle.dump(outdict, f) print('made {}'.format(outpath)) return outdict
_ = kwargs.pop('vmax') #unset vmax from astroquery.mast import Tesscut from astroquery.mast import Catalogs ticid = 307214209 target = "TIC %u" % ticid size = 13 catalogData = Catalogs.query_criteria(catalog="Tic", ID=ticid) ra = catalogData['ra'] dec = catalogData['dec'] coord = "%f, %f" % (ra, dec) hdulist = Tesscut.get_cutouts(coord, size=size) n = 1 # There is more than one sector, we chose the second one # Pull out the location of the middle of the CCD from the Physics WCS in the header. image_head = hdulist[n][1].header prime_head = hdulist[n][0].header ap_head = hdulist[n][2].header col_center = image_head['1CRV4P'] row_center = image_head['2CRV4P'] print("Header col,row: %f, %f" % (col_center, row_center)) # Get the image of the median of the time series. image_array = hdulist[n][1].data['FLUX'] image_stack = np.median(image_array, axis=0) sortedindex = np.dstack(
def my_animation(ticid, istart, istop, flare=None): Writer = animation.writers['imagemagick'] Writer = Writer(fps=20, metadata=dict(artist='Me'), bitrate=1800) starName = "TIC " + str(ticid) radSearch = 4 / 60 #radius in degrees #Querying RA and DEC from Catalogs given a TIC ID catalogData = Catalogs.query_object(starName, radius=radSearch, catalog="TIC") ra = catalogData[0]['ra'] dec = catalogData[0]['dec'] #Gets Skycoord given RA and DEC then calls to TESScut obj_coord = SkyCoord(ra, dec, unit="deg") print(obj_coord) Tesscut.get_sectors(obj_coord) cutout_hdu = Tesscut.get_cutouts(obj_coord, size=20)[0] cutout_hdu.info() cutout_table = cutout_hdu[1].data cutout_table.columns def find_index(btjd): return (np.abs(cutout_table['TIME'] - btjd)).argmin() start = find_index(istart) end = find_index(istop) print(f"Frames {istart}-{istop} ({istop-istart} frames)") def make_animation(data_array, start_frame=start, end_frame=end, vmin=None, vmax=None, delay=50): """ Function that takes an array where each frame is a 2D image array and make an animated plot that runs through the frames. Note: This can take a long time to run if you have a lot of frames. Parameters ---------- data_array : array Array of 2D images. start_frame : int The index of the initial frame to show. Default is the first frame. end_frame : int The index of the final frame to show. Default is the last frame. vmin : float Data range min for the colormap. Defaults to data minimum value. vmax : float Data range max for the colormap. Defaults to data maximum value. delay: Delay before the next frame is shown in milliseconds. Returns ------- response : `animation.FuncAnimation` """ if not vmin: vmin = np.min(data_array) if not vmax: vmax = np.max(data_array) if not end_frame: end_frame = len(data_array) - 1 # set to the end of the array num_frames = end_frame - start_frame + 1 # include the end frame def animate(i, fig, ax, binarytab, start=start): """Function used to update the animation""" ax.set_title("Epoch #" + str(i + start)) fig.suptitle(f'TIC {ticid}') im = ax.imshow(binarytab[i + start], cmap=plt.cm.YlGnBu_r, vmin=vmin, vmax=vmax) return im # Create initial plot. fig, ax = plt.subplots(figsize=(10, 10)) ax.imshow(data_array[start_frame], cmap=plt.cm.YlGnBu_r, vmin=vmin, vmax=vmax) ani = animation.FuncAnimation(fig, animate, fargs=(fig, ax, data_array, start_frame), frames=num_frames, interval=delay, repeat_delay=1000) ani.save('/Users/jshabazz/Work/TESScut_anims/' + str(ticid) + '_flareevent' + str(flare) + '.gif', writer=Writer) print('File created') plt.close() return ani make_animation(cutout_table['FLUX'], vmax=500)