Plotting light curves

LSST light curves can be tricky to plot, so we’ve provided an easy method for a single light curve.

If you’d like to do anything more complicated, like multiple light curves on a single grid, you should consider your own plotting methods.

By default, our methods use the Rubin-recommended palattes, which try to make the plots colorblind-friendly.

Fetch some catalog data

We will use mock DP1 data. This data has been fuzzed to show the general structure of a HATS DP1 catalog, without exposing protected Rubin data.

Note that we have two different light curves on the diaObject table: diaSource and diaObjectForcedSource. You should consider which is more appropriate for your science use case.

[1]:
import lsdb
from lsdb_rubin.plot_light_curve import plot_light_curve
[2]:
dia_object = lsdb.open_catalog("../../tests/data/mock_dp1_1000")
dia_object = dia_object.compute()
dia_object
[2]:
  diaObjectId ra dec nDiaSources radecMjdTai tract diaSource diaObjectForcedSource
164880635168346054 4649294066630237364 32.454472 35.990116 24 60644.727423 531
visit detector ... scienceMag scienceMagErr
2024115005682 1 ... 32.278538 2.077526
+23 rows ... ... ... ...
parentObjectId coord_ra ... psfMagErr midpointMjdTai
0 23.982853 ... 4.263352 60638.638637
+24 rows ... ... ... ...
264907950746260169 4624929140954397868 10.687421 68.569475 23 60651.313693 9273
visit detector ... scienceMag scienceMagErr
2024120100556 0 ... 14.280432 0.32603
+22 rows ... ... ... ...
parentObjectId coord_ra ... psfMagErr midpointMjdTai
0 31.223755 ... 3.523922 60638.151575
+26 rows ... ... ... ...
239647224744314464 4649822373104108975 77.935377 64.983096 26 60649.146059 2392
visit detector ... scienceMag scienceMagErr
2024115797764 0 ... 15.883984 0.262028
+25 rows ... ... ... ...
parentObjectId coord_ra ... psfMagErr midpointMjdTai
0 15.542584 ... 5.792558 60638.861268
+31 rows ... ... ... ...
110828807158025334 4658315645230505927 54.055610 36.212969 29 60644.832787 489
visit detector ... scienceMag scienceMagErr
2024115628387 2 ... 17.784328 1.174745
+28 rows ... ... ... ...
parentObjectId coord_ra ... psfMagErr midpointMjdTai
0 19.511847 ... 1.698166 60638.1216
+32 rows ... ... ... ...
274570109399128569 4681220430264917018 46.916148 77.036664 26 60638.188747 5329
visit detector ... scienceMag scienceMagErr
2024113884443 2 ... 16.140474 2.926271
+25 rows ... ... ... ...
parentObjectId coord_ra ... psfMagErr midpointMjdTai
0 64.692012 ... 0.104414 60638.408643
+28 rows ... ... ... ...
... ... ... ... ... ... ...
1000 rows x 8 columns

Basic usage

You MUST provide a single light curve as the first argument. This is the entire contents of the lightcurve nested data frame.

This is the only required argument, however, and we will use the psfMag column by default.

[3]:
plot_light_curve(dia_object.iloc[0]["diaObjectForcedSource"])
../_images/notebooks_plot_light_curves_5_0.png

Using a different brightness

You can use either a magnitude or flux column. Straight from the Rubin Butler, you will only have flux, but the HATS pipeline adds magnitudes (and magnitude errors) from flux (and flux error) columns.

If you set a flux column, the y-axis will be un-inverted.

[4]:
plot_light_curve(dia_object.iloc[0]["diaSource"], mag_field="scienceMag")
../_images/notebooks_plot_light_curves_7_0.png
[5]:
plot_light_curve(dia_object.iloc[0]["diaSource"], flux_field="scienceFlux")
../_images/notebooks_plot_light_curves_8_0.png

Phase-folded light curves

Our example light curves are not pretty, but we can show them phase-folded by simply providing a period argument, in days. This will fold the light curve according to the provided period, and the x-axis reflects the phase in the period.

[6]:
plot_light_curve(dia_object.iloc[0]["diaSource"], period=1.2)
../_images/notebooks_plot_light_curves_10_0.png
[7]:
plot_light_curve(dia_object.iloc[0]["diaSource"], period=1.2, num_periods=3, period_mjd0=60640.4)
../_images/notebooks_plot_light_curves_11_0.png

Incomplete band data

If you are missing data in one or more bands, those will not appear in the legend. The following light curve doesn’t have any r-band observations.

[8]:
missing_r = dia_object.query("diaObjectId == 4670308463850921897")
plot_light_curve(missing_r.iloc[0]["diaObjectForcedSource"])
../_images/notebooks_plot_light_curves_13_0.png

Customizing appearance

While we use the default Rubin color-blind friendly palatte, that might not work for you for whatever reason. For visual aspects of the plot that will vary by band, you can pass in a dictionary that maps the band string to the desired value.

  • filter_colors

  • filter_symbols

  • filter_linestyles

The first example uses a built-in color palatte, while the second example defines a new map.

[9]:
from lsdb_rubin.plot_light_curve import (
    plot_filter_colors_rainbow,
    plot_linestyles,
    plot_linestyles_none,
)

plot_light_curve(
    dia_object.iloc[0]["diaSource"],
    filter_colors=plot_filter_colors_rainbow,
    filter_linestyles=plot_linestyles,
)
../_images/notebooks_plot_light_curves_15_0.png
[10]:
color_map = {
    "y": "#0c71ff",  # Blue
    "z": "#49be61",  # Green
    "i": "#ff0000",  # Red
    "r": "#ffc200",  # Orange/Yellow
    "g": "#f341a2",  # Pink/Magenta
    "u": "#990099",  # Purple
}
plot_light_curve(dia_object.iloc[0]["diaSource"], filter_colors=color_map)
../_images/notebooks_plot_light_curves_16_0.png

You can also override a single value of the existing by-filter maps. In this case, we’re adding a line only in the r band.

[11]:
plot_light_curve(
    dia_object.iloc[0]["diaSource"],
    filter_linestyles=plot_linestyles_none | {"r": "--"},
)
../_images/notebooks_plot_light_curves_18_0.png

About

Authors: Melissa DeLucchi

Last updated on: Aug 12, 2025

If you use lsdb for published research, please cite following the instructions here.