Hi’iaka occultation#

Hiʻiaka is the largest, outer moon of the trans-Neptunian dwarf planet Haumea. We observed Hiʻiaka occulting a bright star, helping in the study of the moon’s orbital and physical parameters.

This observation was done with the 1-m telescope Artemis and consists of 1 s. short exposures, requiring images to be small in size (46x41 pixels to reduce the overhead time of the telescope). In this tutorial, we will extract the raw flux time-series of the star occulted by Hi’iaka.

Hide code cell content
import warnings

warnings.simplefilter("ignore")

Images#

We start by scanning our dataset

from prose import FitsManager, utils

fm = FitsManager("/Users/lgrcia/data/Hiaka_occultation_20220609_Artemis", depth=1)
fm.observations(hide_exposure=False)
INFO telescope  not found - using default
date telescope filter type target width height exposure files
id
1 2022-06-09 Clear light 2002MS4_Artemis_clear_2x2bin 46 41 1.0 556
2 2022-06-09 bias 2002MS4_Artemis_clear_2x2bin 46 41 0.0 5

For this observation we only have bias calibration images. We see that some images could not be recognized. To solve this problem we can define an Image loader with the telescope pre-defined

Reference#

We then detect the stars for which the photomety will be extracted

from prose import Sequence, blocks, FITSImage

images = fm.all_images
ref = FITSImage(images[0])

calibration = Sequence(
    [
        blocks.Calibration(bias=fm.all_bias, loader=FITSImage),
        blocks.PointSourceDetection(n=1),
    ]
)

calibration.run(ref, show_progress=False, loader=FITSImage)

Let’s vizualize the calibrated reference and define the radii of the apertures used to perform the photometry

import numpy as np

ref.show(zscale=False, sources=False)

radii = np.linspace(1, 6, 20)
for r in radii:
    ref.sources[0].plot(r, label=False, c="w")

rin, rout = 8, 12
ref.sources[0].plot(rin, label=False, c="y")
ref.sources[0].plot(rout, label=False, c="y")
../../_images/0c18bffa16ed4a461c607a71fe61f0473f3672e27272ec821e411ab89584763e.png

The reduction sequence#

def copy_sources(image):
    image.sources = ref.sources.copy()


reduction = Sequence(
    [
        *calibration,
        blocks.Apply(copy_sources),  # copy sources from ref
        blocks.CentroidQuadratic(limit=4),  # centroiding
        blocks.AperturePhotometry(scale=False, radii=radii),  # aperture photometry
        blocks.AnnulusBackground(
            scale=False, rin=rin, rout=rout
        ),  # local background estimate
        blocks.Get(path=lambda im: im.metadata["path"]),
        blocks.GetFluxes(),
    ]
)

reduction.run(images, loader=FITSImage)

We can now retrieve our data from the GetFluxes block and proceed with differential photometry

import matplotlib.pyplot as plt

fluxes = reduction[-1].fluxes.copy()
fluxes.time -= 2450000

fluxes.target = 0
diff_fluxes = fluxes.diff()
diff_fluxes.estimate_best_aperture(0)
diff_fluxes.plot(color="0.3", ls="-")
_ = plt.xlim(9740.728, 9740.731)
../../_images/f20dfb6610c7ec0f63faf45ad55e9f45121f8401ecdac558ebd0cb12c87202e6.png

This is a full occultation that we should be able to see on the images directly!

Seeing the star disapear#

In order to see the images as they are processed, we will use the VideoPlot block. It takes a plotting function as argument, which takes as input an Image object. Let’s implement it

def plot(image):
    plt.figure(None, (10, 4))
    ax = plt.subplot(121, xlabel="JD-utc - 2450000", ylabel="diff. flux")
    t0 = image.jd - 2450000
    mask = diff_fluxes.time < t0
    ax.plot(diff_fluxes.time[mask], diff_fluxes.flux[mask], ".-", c="0.3")
    plt.xlim(9740.7285, 9740.7305)
    ax.set_ylim(-0.2, 1.3)
    ax.set_title(f"Artemis 2002MS4 occultation ({ref.date.date()})")

    ax2 = plt.subplot(122)
    image.show(zscale=False, ax=ax2, sources=False)
    image.sources.plot(radius=5, ax=ax2)
    plt.tight_layout()

and use it within a sequence that also contain the photometric extraction blocks

viz = Sequence([*reduction[0:-2], blocks.VideoPlot(plot, "hiaka.mp4", fps=17)])

# Only the images close to the occultation
occ_images = reduction.get.path[(fluxes.time > 9740.7285) & (fluxes.time < 9740.7305)]
viz.run(occ_images, loader=FITSImage)
IMAGEIO FFMPEG_WRITER WARNING: input image is not divisible by macro_block_size=16, resizing from (1000, 400) to (1008, 400) to ensure video compatibility with most codecs and players. To prevent resizing, make your input image divisible by the macro_block_size or set the macro_block_size to 1 (risking incompatibility).

Here is the movie where we indeed see the star being occulted

Note

Setting limit=3 in CentroidQuadratic allows to keep the aperture fixed when the star’s centroid is farther than limit pixel away from the initial position (we see that on the video when the star is occulted)