Astrocut Documentation

Astrocut is a powerful Python package for generating cutouts from sets of astronomical images with overlapping footprints.

It supports both two-dimensional images and three-dimensional image cubes, making it versatile for a wide range of astronomical data. Astrocut is compatible with multiple file formats, including FITS, ASDF, and TESS full-frame images. Beyond cutout extraction, the package includes features for post-processing, such as aligning cutouts along a path and combining multiple cutouts for enhanced analysis.

Astrocut is actively maintained and continuously evolving to support the needs of the astronomical community.

Image Cutouts

Astrocut can generate cutouts of image data from FITS and ASDF files using the FITSCutout and ASDFCutout classes, respectively. The package supports both single and multiple cutouts, allowing users to extract data from a single image or multiple images with overlapping footprints.

Both image cutout classes take the following parameters:

  • input_files: A list of input image files in the expected format. These can be local file paths, URLs, or S3 URIs.

  • coordinates: The coordinates at the center of the cutout.

  • cutout_size: The size of the cutout in pixels or angular units.

  • fill_value: If the cutout footprint falls outside of the image, this value will be used to fill the missing pixels.

FITS Cutouts

The Flexible Image Transport System (FITS) is a standard format for astronomical data. Astrocut can generate cutouts from FITS files and return the results in memory or as a written file, depending on the user’s preference. The cutout ‘~astropy.fits.io.HDUList’ object format is described in the Astrocut File Fomats page.

To make a cutout from a FITS file or files, use the FITSCutout class.

>>> from astrocut import FITSCutout
>>> from astropy.coordinates import SkyCoord

>>> input_files = ["https://archive.stsci.edu/pub/hlsp/candels/cosmos/cos-tot/v1.0/hlsp_candels_hst_acs_cos-tot-sect23_f606w_v1.0_drz.fits",
...                "https://archive.stsci.edu/pub/hlsp/candels/cosmos/cos-tot/v1.0/hlsp_candels_hst_acs_cos-tot-sect23_f814w_v1.0_drz.fits"]

>>> center_coord = SkyCoord("150.0945 2.38681", unit="deg")
>>> cutout_size = [200, 300]
>>> fits_cutout = FITSCutout(input_files=input_files,
...                          coordinates=center_coord,
...                          cutout_size=cutout_size,
...                          single_outfile=True)

The resulting FITSCutout object can be used to access the cutout data and metadata. The cutouts_by_file attribute is a dictionary that stores the individual cutouts as a list of CutoutInstance objects by input filename. The CutoutInstance object contains the cutout data, shape, world coordinate system (WCS) and other helpful properties.

The hdu_cutouts_by_file attribute is a dictionary that stores the cutouts as a list of ImageHDU objects by input filename. These objects can be used to access cutout data and metadata in the HDU header.

The fits_cutouts attribute is a list of cutouts as HDUList objects. The single_outfile parameter decides whether all the cutouts will be written to a single HDUList object or to separate objects. When single_outfile is set to True, a single HDUList object will contain all the cutouts.

>>> cutout = fits_cutout.fits_cutouts[0]
>>> cutout.info()
Filename: (No file associated with this HDUList)
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU       9   ()
  1  CUTOUT        1 ImageHDU      2767   (200, 300)   float32
  2  CUTOUT        1 ImageHDU      3343   (200, 300)   float32

To write the cutouts and their metadata to FITS files, use the write_as_fits method. This method returns a list of paths to the cutout FITS files.

>>> from astropy.io import fits

>>> path = fits_cutout.write_as_fits()
>>> print(path)
['cutout_150.0945000_2.3868100_200-x-300_astrocut.fits']

>>> with fits.open(path[0]) as hdul:
...     hdul.info()
Filename: cutout_150.0945000_2.3868100_200-x-300_astrocut.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      11   ()
  1  CUTOUT        1 ImageHDU      2769   (200, 300)   float32
  2  CUTOUT        1 ImageHDU      3345   (200, 300)   float32

By default, the cutouts are written to the current working directory. You can specify a different output directory using the output_dir parameter. You can also set the prefix of the cutout file paths using the cutout_prefix parameter. The default value is “cutout”.

ASDF Cutouts

The Advanced Scientific Data Format (ASDF) is a flexible format for storing scientific data. Astrocut can generate cutouts from ASDF files and return the results in memory or as a written file, depending on the user’s preference. The cutout ASDF file format is described in the Astrocut File Formats page.

To make a cutout from an ASDF file or files, use the ASDFCutout class.

>>> from astrocut import ASDFCutout
>>> from astropy.coordinates import SkyCoord

>>> input_files = [""]  # Path(s) to local ASDF file, URL, or S3 URI

>>> center_coord = SkyCoord("80.15189743 29.74561219", unit="deg")
>>> cutout_size = 25
>>> asdf_cutout = ASDFCutout(input_files=input_files,
...                          coordinates=center_coord,
...                          cutout_size=cutout_size) 

Warning

Due to the symmetry of the pixel grid, odd values for cutout_size generally produce cutouts that are more accurately centered on the target coordinates than even values for cutout_size.

The resulting ASDFCutout object can be used to access the cutout science data and metadata. The cutouts_by_file attribute is a dictionary that stores the individual science data cutouts as a list of Cutout2D objects by input filename. The Cutout2D object contains the science cutout data, shape, world coordinate system (WCS) and other helpful properties. The cutouts attribute is a list of science data cutouts as Cutout2D objects, one for each input file.

The asdf_cutouts attribute is a list of cutouts as AsdfFile objects, and the fits_cutout attribute is a list of cutouts as HDUList objects. The cutout objects in these lists can be used to access cutout data and metadata, as shown below.

Note

Although Astrocut supports writing ASDF cutouts as FITS objects, we recommend using the ASDF output format whenever possible. FITS files may not accurately represent the ASDF world coordinate system, so saving cutouts in their original format will generally give the most reliable results.

>>> cutout_asdf = asdf_cutout.asdf_cutouts[0] 
>>> cutout_asdf.info() 
root (AsdfObject)
├─asdf_library (Software)
│ ├─author (str): The ASDF Developers
│ ├─homepage (str): http://github.com/asdf-format/asdf
│ ├─name (str): asdf
│ └─version (str): 4.1.0
├─history (dict)
│ ├─extensions (list)
│ │ ├─[0] (ExtensionMetadata) ...
│ │ ├─[1] (ExtensionMetadata) ...
│ │ └─6 not shown
│ └─entries (list) ...
└─roman (TaggedDict)
  ├─meta (dict) ...
  ├─data (ndarray) ...
  ├─context (ndarray) ...
  ├─err (ndarray) ...
  ├─weight (ndarray) ...
  ├─var_poisson (ndarray) ...
  ├─var_rnoise (ndarray) ...
  ├─var_flat (ndarray) ...
  ├─cal_logs (CalLogs) # Calibration Log Messages ...
  └─individual_image_cal_logs (list) ...
Some nodes not shown.

>>> cutout_fits = asdf_cutout.fits_cutouts[0] 
>>> cutout_fits.info() 
Filename: (No file associated with this HDUList)
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      11   ()
  1  CUTOUT        1 ImageHDU        67   (25, 25)   float32
  2  ASDF          1 BinTableHDU     13   1R x 1C   ['36470B']

To write the cutouts and their metadata to ASDF files, use the write_as_asdf method. This method returns a list of paths to the cutout ASDF files.

>>> import asdf

>>> path = asdf_cutout.write_as_asdf() 

>>> with asdf.open(path[0]) as af:
...     print(af['roman']['data'].shape) 
(25, 25)

To write the cutouts and their metadata to FITS files, use the write_as_fits method. This method returns a list of paths to the cutout FITS files.

>>> from astropy.io import fits

>>> path = asdf_cutout.write_as_fits() 

>>> with fits.open(path[0]) as hdul:
...     hdul.info() 
Filename: r0099101001001001001_F158_visit_r274dp63x31y81_i2d_269.6970000_66.0450000_25-x-25_astrocut.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      11   ()
  1  CUTOUT        1 ImageHDU        67   (25, 25)   float32
  2  ASDF          1 BinTableHDU     13   1R x 1C   [36470B]

By default, the cutouts are written to the current working directory. You can specify a different output directory using the output_dir parameter in either of the write functions.

Lite Mode

By default, ASDFCutout creates cutouts of all arrays in the input file (e.g., data, error, uncertainty, variance, etc.) where the last two dimensions match the shape of the science data array. It also preserves all of the metadata from the input file. These cutout arrays and metadata can be accessed through the asdf_cutouts attribute.

For large input files, this can result in large output cutouts. If you only require the science data and the updated world coordinate system, you can set the lite parameter to True. With this option enabled, only the science data array is cut out and returned, and metadata is reduced to the sliced GWCS object needed to interpret the cutout. This makes the output cutouts smaller and faster to create, while still retaining essential information for science analysis.

>>> asdf_cutout_lite = ASDFCutout(input_files=input_files,
...                               coordinates=center_coord,
...                               cutout_size=cutout_size,
...                               lite=True) 
>>> cutout_asdf_lite = asdf_cutout_lite.asdf_cutouts[0] 
>>> cutout_asdf_lite.info() 
root (AsdfObject)
└─roman (dict)
  ├─meta (dict)
  │ └─wcs (WCS)
  └─data (ndarray): shape=(25, 25), dtype=float32

Image Outputs

Both the FITSCutout and ASDFCutout classes provide methods to normalize the cutout data and write it as an image, either as a a Image object or a file.

To create cutouts as Image objects, use the get_image_cutouts method. You can provide the following normalization parameters:

  • stretch: The stretch function to apply to the image array. Options include “asinh”, “sinh”, “sqrt”, “log”, and “linear”.

  • minmax_percent: Defines an interval for scaling the image based on percentiles. The format is [lower percentile, upper percentile], where pixel values outside this range are clipped. Only one of minmax_percent and minmax_value should be specified.

  • minmax_value: Defines an interval for scaling the image based on values. The format is [min value, max value], where pixel values outside this range are clipped. Only one of minmax_percent and minmax_value should be specified.

  • invert: A boolean value that determines whether the image should be inverted.

>>> fits_img = fits_cutout.get_image_cutouts(stretch='linear', minmax_percent=[10, 99])[1]
>>> print(fits_img.size)
(200, 300)
>>> fits_img.show() 
../_images/img_cutout.jpg

To produce a colorized RGB image, set the colorize parameter to True. Color images require three cutouts, which will be treated as the R, G, and B channels, respectively.

>>> from astrocut import FITSCutout
>>> from astropy.coordinates import SkyCoord

>>> input_files = ["https://archive.stsci.edu/pub/hlsp/goods/v2/h_nz_sect14_v2.0_drz_img.fits",
...                "https://archive.stsci.edu/pub/hlsp/goods/v2/h_ni_sect14_v2.0_drz_img.fits",
...                "https://archive.stsci.edu/pub/hlsp/goods/v2/h_nv_sect14_v2.0_drz_img.fits"]

>>> center_coord = SkyCoord("189.51522 62.2865221", unit='deg')
>>> cutout_size = [200, 300]

>>> color_image = FITSCutout(input_files, center_coord, cutout_size).get_image_cutouts(colorize=True)[0]
>>> color_image.show() 
../_images/img_cutout_color.png

To write the cutouts to image files, use the astrocut.FITSCutout.write_as_img method. This method returns a list of paths to the cutout image files. astrocut.FITSCutout.write_as_img takes the same normalization parameters as astrocut.FITSCutout.get_image_cutouts.

To specify the output format of the cutout images, use the output_format parameter.

>>> from PIL import Image

>>> path = fits_cutout.write_as_img(stretch='sqrt', invert=True, output_format='png')
>>> im = Image.open(path[0]) 
../_images/img_cutout_invert.png

By default, the cutouts are written to the current working directory. You can specify a different output directory using the output_dir parameter. You can also set the prefix of the cutout file paths using the cutout_prefix parameter. The default value is “cutout”.

Cube Cutouts

Astrocut enables the creation of cutouts from image cube files, including TESS full-frame images (FFIs). Supported products are from the Science Processing Operations Center (SPOC).

To begin, the CubeFactory class constructs a large image cube from a list of FFI files, optimizing the writing process for efficiency. The TessCubeCutout class then extracts the desired cutout and generates a target pixel file (TPF) similar to those produced by the TESS Mission.

For a small number of cutouts, the TESSCut web service may suit your needs.

Note

Starting in version 1.1.0, the ability to create image cubes and cube cutouts using TESS Image Calibration (TICA) full frame images is deprecated and will be removed in a future release. Individual TICA full-frame images will remain available from the MAST TICA homepage.

Making Image Cubes

Important

Time-Memory Trade-off

Making an image cube is a simple operation, but comes with an important time-memory trade-off.

The max_memory argument determines the maximum memory in GB that will be used for the image data cube while it is being built. This is the amount of memory required only for the data cube, so is somewhat smaller than the total amount of memory needed for the program to run. You should never set it to your system’s total memory.

Because of this, cube files do not need to allocate their total size in memory all at once. Instead, a smaller memory allocation can be used while the cube file is constructed; however, this will significantly increase the execution time as bytes are swapped into and out of the memory allocation being used. The default value of 50 GB was chosen because it fits all of the TESS FFIs from a single Prime Mission Sector (Sectors 1-26); however, in the current TESS Extended Mission 2, where 6 times more FFIs are observed per Sector (compared to the number of FFIs observed per Sector in the Prime Mission), 50 GB is not enough space to hold all of the FFIs in memory, and the cubes will be written in multiple blocks. With the default settings, on a system with 64 GB of memory, it takes about 3 hours to build a single cube file. On a system with less memory or where max_memory is set to a value less than 50 GB, more passes through the list of files are required, and the time to create a cube can increase significantly.

Assuming that you have set of calibrated TESS FFI files stored locally, you can create a cube using the make_cube method. By default, make_cube runs in verbose mode and prints out progress; setting the verbose parameter to False will silence all output.

Note, you can only make cubes from a set of FFIs that were observed in the same sector, camera, and CCD.

The output image cube file format is described in the Astrocut File Formats page.

>>> from astrocut import CubeFactory
>>> from glob import glob
>>> from astropy.io import fits

>>> my_cuber = CubeFactory()
>>> input_files = glob("data/*ffic.fits")

>>> cube_file = my_cuber.make_cube(input_files) 
Completed file 0
Completed file 1
Completed file 2
.
.
.
Completed file 142
Completed file 143
Total time elapsed: 46.42 sec
File write time: 8.82 sec

>>> print(cube_file) 
img-cube.fits

>>> cube_hdu = fits.open(cube_file) 
>>> cube_hdu.info()  
Filename: img-cube.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
0  PRIMARY       1 PrimaryHDU      28   ()
1                1 ImageHDU         9   (2, 144, 2136, 2078)   float32
2                1 BinTableHDU    302   144R x 147C   [24A, J, J, J, J, J, J, D, 24A, J, 24A, 24A, J, J, D, 24A, 24A, 24A, J, D, 24A, D, D, D, D, 24A, 24A, D, D, D, D, D, 24A, D, D, D, D, J, D, D, D, D, D, D, D, D, D, D, D, D, J, J, D, J, J, J, J, J, J, J, J, J, J, D, J, J, J, J, J, J, D, J, J, J, J, J, J, D, J, J, J, J, J, J, D, J, J, J, J, J, J, J, J, 24A, D, J, 24A, 24A, D, D, D, D, D, D, D, D, J, J, D, D, D, D, D, D, J, J, D, D, D, D, D, D, D, D, D, D, D, D, 24A, J, 24A, 24A, J, J, D, 24A, 24A, J, J, D, D, D, D, J, 24A, 24A, 24A]

Making Cutout Target Pixel Files

Astrocut can generate cutout target pixel files from TESS cubes using the astrocut.TessCubeCutout class and return the results in memory or as a file, depending on the user’s preference. The cutout target pixel file format is described in the Astrocut File Formats page.

The astrocut.TessCubeCutout class takes the following parameters:

  • input_files: A list of input cube files in the expected format. These can be local file paths, URLs, or S3 URIs.

  • coordinates: The coordinates at the center of the cutout.

  • cutout_size: The size of the cutout in pixels or angular units.

  • fill_value: If the cutout footprint falls outside of the image, this value will be used to fill the missing pixels.

>>> from astrocut import TessCubeCutout
>>> from astropy.io import fits

>>> cube_file = "img-cube.fits"
>>> cube_cutout = TessCubeCutout(cube_file,
...                              coordinates="251.51 32.36",
...                              cutout_size=5)  

The resulting TessCubeCutout object can be used to access the cutout data and metadata. The cutouts_by_file attribute is a dictionary that stores the individual cutouts as a list of CubeCutoutInstance objects by input filename. The CubeCutoutInstance object contains the cutout data, shape, world coordinate system (WCS), and other helpful properties.

The tpf_cutouts_by_file attribute is a dictionary that stores the cutouts as a list of HDUList objects by input filename. These objects are in the format of target pixel files and can be used to access cutout data and metadata in the HDU header. The tpf_cutouts attribute is a list of cutouts as HDUList objects in the format of target pixel files.

>>> tpf_cutout = cube_cutout.tpf_cutouts[0] 
>>> tpf_cutout.info() 
Filename: (No file associated with this HDUList)
No.    Name      Ver    Type      Cards   Dimensions   Format
0  PRIMARY       1 PrimaryHDU      42   ()
1  PIXELS        1 BinTableHDU    222   144R x 12C   [D, E, J, 25J, 25E, 25E, 25E, 25E, J, E, E, 38A]
2  APERTURE      1 ImageHDU        45   (5, 5)   float64

To write the cutout target pixel files to FITS files, use the write_as_tpf method. This method returns a list of paths to the cutout TPF files. The file names will be in the pattern of “<cube_file_base>_<ra>_<dec>_<cutout_size>_astrocut.fits”.

>>> from astropy.io import fits

>>> path = cube_cutout.write_as_tpf() 
>>> print(path) 
['img_251.51_32.36_5x5_astrocut.fits']

>>> with fits.open(path[0]) as hdul:
...     hdul.info() 
Filename: img_251.51_32.36_5x5_astrocut.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
0  PRIMARY       1 PrimaryHDU      42   ()
1  PIXELS        1 BinTableHDU    222   144R x 12C   [D, E, J, 25J, 25E, 25E, 25E, 25E, J, E, E, 38A]
2  APERTURE      1 ImageHDU        45   (5, 5)   float64

By default, the cutouts are written to the current working directory. You can specify a different output directory using the output_dir parameter.

Multithreading

Using cube files stored on the cloud allows you the option to implement multithreading to improve cutout generation speed. See below for a multithreaded example, using a TESS cube file stored on AWS.

To use multithreading for cloud-based cutouts, set the threads argument in cube_cut to the number of threads you want to use. Alternatively, you can set threads to "auto", which will set the number of threads based on the CPU count of your machine. Note that Total Time results may vary from machine to machine.

>>> from astrocut import TessCubeCutout
>>> from astropy.coordinates import SkyCoord

>>> coord = SkyCoord(217.42893801, -62.67949189, unit="deg", frame="icrs")
>>> cutout_size = 30
>>> cube_file = "s3://stpubdata/tess/public/mast/tess-s0038-2-2-cube.fits"

>>> cube_cutout = TessCubeCutout(cube_file,
...                              coordinates=coord,
...                              cutout_size=cutout_size,
...                              verbose=True,
...                              threads="auto") 
DEBUG: Coordinates: <SkyCoord (ICRS): (ra, dec) in deg
  (217.42893801, -62.67949189)> [Cutout]
DEBUG: Cutout size: [30 30] [Cutout]
DEBUG: Using WCS from row 1852 out of 3705 [CubeCutout]
DEBUG: Image cutout cube shape: (3705, 30, 30) [CubeCutout]
DEBUG: Uncertainty cutout cube shape: (3705, 30, 30) [CubeCutout]
DEBUG: Cutout center coordinate: 217.42893801, -62.67949189 [CubeCutout]
DEBUG: Maximum distance between approximate and true location: 0.0 [CubeCutout]
DEBUG: Error in approximate WCS (sigma): 0.0000 [CubeCutout]
DEBUG: Total time: 3.94 sec [CubeCutout]

The same call made without multithreading enabled will result in a longer processing time, depending on the cutout size. Note that multithreading is disabled by default.

>>> cube_cutout = TessCubeCutout(cube_file,
...                              coordinates=coord,
...                              cutout_size=cutout_size,
...                              verbose=True) 
DEBUG: Coordinates: <SkyCoord (ICRS): (ra, dec) in deg
  (217.42893801, -62.67949189)> [Cutout]
DEBUG: Cutout size: [30 30] [Cutout]
DEBUG: Using WCS from row 1852 out of 3705 [CubeCutout]
DEBUG: Image cutout cube shape: (3705, 30, 30) [CubeCutout]
DEBUG: Uncertainty cutout cube shape: (3705, 30, 30) [CubeCutout]
DEBUG: Cutout center coordinate: 217.42893801, -62.67949189 [CubeCutout]
DEBUG: Maximum distance between approximate and true location: 0.0 [CubeCutout]
DEBUG: Error in approximate WCS (sigma): 0.0000 [CubeCutout]
DEBUG: Total time: 9.65 sec [CubeCutout]

Footprint Cutouts

Astrocut can create cutouts without input files by matching the cutout’s footprint to the footprints of available data products on the cloud.

The TessFootprintCutout class generates cutouts from TESS image cube files stored in MAST’s AWS Open Data Bucket. Simply provide the target coordinates and cutout size, and the class will match the cutout’s footprint to the footprints of available cube files on the cloud. A cutout target pixel file will be generated for each matching cube file. To restrict the cutouts to specific sectors, use the sequence parameter with a sector number or a list of sector numbers. If sequence is set to None, cutouts will be returned for all matching cube files.

The resulting cutouts can be returned in memory or as a file, depending on the user’s preference. The cutout target pixel file format is described in the Astrocut File Formats page.

>>> from astrocut import TessFootprintCutout

>>> fp_cutout = TessFootprintCutout(
...         coordinates='83.40630967798376 -62.48977125108528',
...         cutout_size=10,
...         sequence=[1, 2])  # TESS sectors
>>> fp_cutout.write_as_tpf()  

The resulting TessFootprintCutout object can be used to access the cutout data and metadata. The cutouts_by_file attribute is a dictionary that stores the individual cutouts as a list of CubeCutoutInstance objects by input filename. The CubeCutoutInstance object contains the cutout data, shape, world coordinate system (WCS), and other helpful properties.

The tpf_cutouts_by_file attribute is a dictionary that stores the cutouts as a list of HDUList objects by input filename. These objects are in the format of target pixel files and can be used to access cutout data and metadata in the HDU header. The tpf_cutouts attribute is a list of cutouts as HDUList objects in the format of target pixel files.

>>> tpf_cutout = fp_cutout.tpf_cutouts[0]
>>> tpf_cutout.info() 
Filename: (No file associated with this HDUList)
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      55   ()
  1  PIXELS        1 BinTableHDU    144   1282R x 12C   ['D', 'E', 'J', '100J', '100E', '100E', '100E', '100E', 'J', 'E', 'E', '38A']
  2  APERTURE      1 ImageHDU        80   (10, 10)   int32

To write the cutout target pixel files to FITS files, use the write_as_tpf method. This method returns a list of paths to the cutout TPF files.

>>> from astropy.io import fits

>>> path = fp_cutout.write_as_tpf()[0]
>>> print(path)
tess-s0001-4-4_83.4063097_-62.4897713_10-x-10_astrocut.fits

>>> with fits.open(path) as hdul:
...     hdul.info()
Filename: tess-s0001-4-4_83.4063097_-62.4897713_10-x-10_astrocut.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      57   ()
  1  PIXELS        1 BinTableHDU    146   1282R x 12C   [D, E, J, 100J, 100E, 100E, 100E, 100E, J, E, E, 38A]
  2  APERTURE      1 ImageHDU        82   (10, 10)   int32

By default, the cutouts are written to the current working directory. You can specify a different output directory using the output_dir parameter.

Additional Cutout Processing

Path-based Cutouts

The center_on_path function allows the user to take one or more Astrocut cutout TPF(s) and create a single cutout, centered on a moving target that crosses through the file(s). The user can optionally pass in a target object name and FFI WCS object.

The output target pixel file format is described here.

This example starts with a path, and uses several TESScut services to retrieve all of the inputs for the center_on_path function. We also use the helper function path_to_footprints that takes in a path table, cutout size, and WCS object, and returns the cutout location/size(s) necesary to cover the entire path.

>>> import astrocut

>>> import requests  

>>> from astropy.table import Table
>>> from astropy.coordinates import SkyCoord
>>> from astropy.time import Time
>>> from astropy.io import fits
>>> from astropy import wcs

>>> from astroquery.mast import Tesscut  

>>> # The moving target path
>>> path_table = Table({"time": Time([2458468.275827604, 2458468.900827604, 2458469.525827604,
...                                   2458470.150827604, 2458470.775827604], format="jd"),
...                     "position": SkyCoord([82.22813, 82.07676, 81.92551, 81.7746, 81.62425],
...                                          [-1.5821,- 1.54791, -1.5117, -1.47359, -1.43369], unit="deg")
...                    })

>>> # Getting the FFI WCS
>>> resp = requests.get(f"https://mast.stsci.edu/tesscut/api/v0.1/ffi_wcs?sector=6&camera=1&ccd=1")  
>>> ffi_wcs = wcs.WCS(resp.json()["wcs"], relax=True)  
>>> print(ffi_wcs)  
WCS Keywords

Number of WCS axes: 2
CTYPE : 'RA---TAN-SIP'  'DEC--TAN-SIP'
CRVAL : 86.239936828613  -0.87476283311844
CRPIX : 1045.0  1001.0
PC1_1 PC1_2  : 0.0057049915194511  7.5332427513786e-06
PC2_1 PC2_2  : -0.00015248404815793  0.005706631578505
CDELT : 1.0  1.0
NAXIS : 2136  2078

>>> # Making the regular cutout (using astroquery)
>>> size = [15,15]
>>> footprints = astrocut.path_to_footprints(path_table["position"], size, ffi_wcs)  
>>> print(footprints)  
[{'coordinates': <SkyCoord (ICRS): (ra, dec) in deg
     (81.92560877, -1.50880833)>, 'size': (37, 125)}]

>>> manifest = Tesscut.download_cutouts(**footprints[0], sector=6)  
Downloading URL https://mast.stsci.edu/tesscut/api/v0.1/astrocut?ra=81.92560876541987&dec=-1.5088083330171362&y=37&x=125&units=px&sector=6 to ./tesscut_20210707103901.zip ... [Done]
Inflating...

>>> print(manifest["Local Path"][0])  
./tess-s0006-1-1_81.925609_-1.508808_125x37_astrocut.fits

# Centering on the moving target
>>> mt_cutout_fle = astrocut.center_on_path(path_table, size, manifest["Local Path"], target="my_asteroid",
...                                         img_wcs=ffi_wcs, verbose=False)  

>>> cutout_hdu = fits.open(mt_cutout_fle)  
>>> cutout_hdu.info()  
Filename: ./my_asteroid_1468.9120483398438-1470.1412353515625_15-x-15_astrocut.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      56   ()
  1  PIXELS        1 BinTableHDU    152   60R x 16C   [D, E, J, 225J, 225E, 225E, 225E, 225E, J, E, E, 38A, D, D, D, D]
  2  APERTURE      1 ImageHDU        97   (2136, 2078)   int32

Combining Cutouts

The CutoutsCombiner class allows the user to take one or more Astrocut cutout FITS files (as from fits_cut) with a shared WCS object, and combine them into a single cutout. This means that you should request the same cutout size in all of the images you want to combine.

The default setting combines the images with a mean combiner, such that every combined pixel is the mean of all pixels that have data at that point. This mean combiner is made with the build_default_combine_function, which takes the input image HDUs and allows the user to specify a null data value (default is NaN).

Users can write a custom combiner function, either by directly setting the combine_images function, or by writing a custom combiner function builder and passing it to the build_img_combiner function. The main reason to write a function builder is that the combine_images function must work only on the images being combined; any usage of header keywords, for example, must be set in that function. See the build_default_combine_function for an example of how this works.

>>> import astrocut

>>> from astropy.coordinates import SkyCoord

>>> fle_1 = 'hst_skycell-p2381x05y09_wfc3_uvis_f275w-all-all_drc.fits'
>>> fle_2 = 'hst_skycell-p2381x06y09_wfc3_uvis_f275w-all-all_drc.fits'

>>> center_coord = SkyCoord("211.27128477 53.66062066", unit='deg')
>>> size = [30,50]

>>> cutout_1 = astrocut.fits_cut(fle_1, center_coord, size, extension='all',
...                     cutout_prefix="cutout_p2381x05y09", verbose=False)  
>>> cutout_2 = astrocut.fits_cut(fle_2, center_coord, size, extension='all',
...                     cutout_prefix="cutout_p2381x06y09", verbose=False)  

>>> plt.imshow(fits.getdata(cutout_1, 1))  
../_images/hapcut_left.png
>>> plt.imshow(fits.getdata(cutout_2, 1))  
../_images/hapcut_right.png
>>> combined_cutout = astrocut.CutoutsCombiner([cutout_1, cutout_2]).combine("combined_cut.fits")  
>>> plt.imshow(fits.getdata(combined_cutout, 1))  
../_images/hapcut_combined.png

All of the combining can be done in memory, without writing FITS files to disk as well.

>>> import astrocut

>>> from astropy.coordinates import SkyCoord

>>> fle_1 = 'hst_skycell-p2381x05y09_wfc3_uvis_f275w-all-all_drc.fits'
>>> fle_2 = 'hst_skycell-p2381x06y09_wfc3_uvis_f275w-all-all_drc.fits'

>>> center_coord = SkyCoord("211.27128477 53.66062066", unit='deg')
>>> size = [30,50]

>>> cutout_1 = astrocut.fits_cut(fle_1, center_coord, size, extension='all',
...                     cutout_prefix="cutout_p2381x05y09", memory_only=True)[0]  
>>> cutout_2 = astrocut.fits_cut(fle_2, center_coord, size, extension='all',
...                     cutout_prefix="cutout_p2381x06y09", memory_only=True)[0]  

>>> plt.imshow(cutout_1[1].data)  
../_images/hapcut_left.png
>>> plt.imshow(cutout_2[1].data)  
../_images/hapcut_right.png
>>> combined_cutout = astrocut.CutoutsCombiner([cutout_1, cutout_2]).combine(memory_only=True)  
>>> plt.imshow(combined_cutout[1].data)  
../_images/hapcut_combined.png