Skip to content

Commit 93acb7a

Browse files
authored
Merge pull request #27 from astronomy-commons/issue/26/plot
Add method to plot a single light curve.
2 parents d6bac7a + 6c5cad5 commit 93acb7a

File tree

14 files changed

+1048
-1
lines changed

14 files changed

+1048
-1
lines changed

docs/notebooks/plot_light_curves.ipynb

Lines changed: 749 additions & 0 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ classifiers = [
1616
dynamic = ["version"]
1717
requires-python = ">=3.10"
1818
dependencies = [
19-
"lsdb>=0.5.0", # For catalog operations
19+
"lsdb>=0.6.3", # For catalog operations
2020
"skymap-convert>=0.1.1", # For skymap-based methods, such as tract_patch_search
2121
]
2222

src/lsdb_rubin/plot_light_curve.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import matplotlib.pyplot as plt
2+
import nested_pandas as npd
3+
4+
plot_filter_colors_rainbow = {
5+
"u": "#0c71ff", # Blue
6+
"g": "#49be61", # Green
7+
"r": "#ff0000", # Red
8+
"i": "#ffc200", # Orange/Yellow
9+
"z": "#f341a2", # Pink/Magenta
10+
"y": "#990099", # Purple
11+
}
12+
13+
## https://rtn-045.lsst.io/#colorblind-friendly-plots
14+
plot_filter_colors_white_background = {
15+
"u": "#1600ea",
16+
"g": "#31de1f",
17+
"r": "#b52626",
18+
"i": "#370201",
19+
"z": "#ba52ff",
20+
"y": "#61a2b3",
21+
}
22+
plot_filter_colors_black_background = {
23+
"u": "#3eb7ff",
24+
"g": "#30c39f",
25+
"r": "#ff7e00",
26+
"i": "#2af5ff",
27+
"z": "#a7f9c1",
28+
"y": "#fdc900",
29+
}
30+
31+
plot_filter_symbols = {
32+
"u": "o", # Circle
33+
"g": "^", # Triangle up
34+
"r": "s", # Square
35+
"i": "D", # Diamond
36+
"z": "v", # Triangle down
37+
"y": "X", # X
38+
}
39+
40+
plot_symbols = {"u": "o", "g": "^", "r": "v", "i": "s", "z": "*", "y": "p"}
41+
plot_linestyles_none = {
42+
"u": None,
43+
"g": None,
44+
"r": None,
45+
"i": None,
46+
"z": None,
47+
"y": None,
48+
}
49+
50+
plot_linestyles = {
51+
"u": "--",
52+
"g": (0, (3, 1, 1, 1)),
53+
"r": "-.",
54+
"i": "-",
55+
"z": (0, (3, 1, 1, 1, 1, 1)),
56+
"y": ":",
57+
}
58+
59+
band_names_ugrizy = ["u", "g", "r", "i", "z", "y"]
60+
band_names_lsst_ugrizy = ["LSST_u", "LSST_g", "LSST_r", "LSST_i", "LSST_z", "LSST_y"]
61+
62+
63+
def plot_light_curve(
64+
lc: npd.NestedFrame,
65+
title="LSST light curve",
66+
mag_field="psfMag",
67+
flux_field=None,
68+
legend_kwargs=None,
69+
band_names=None,
70+
plot_kwargs=None,
71+
filter_colors=None,
72+
filter_symbols=None,
73+
filter_linestyles=None,
74+
period=None,
75+
num_periods=1,
76+
period_mjd0=None,
77+
):
78+
"""Convenience method to plot a single light curve's magnitude. The y-axis is
79+
upside-down since magnitude is bananas.
80+
81+
If you want additional configuration, you may be better served creating your own plotting
82+
function, as this is intended for quick inspection of individual lightcurves in HATS-formatted
83+
data products.
84+
85+
Args:
86+
lc (npd.NestedFrame): Light curve data a single nested dataframe.
87+
title (str, optional): Title for the plot. Defaults to "LSST light curve".
88+
mag_field (str, optional): Field name for magnitude values. Defaults to "psfMag".
89+
If using magnitude, the y-axis will be inverted.
90+
flux_field (str, optional): Field name for flux values.
91+
If None, uses mag_field instead. Defaults to None.
92+
legend_kwargs (dict, optional): Keyword arguments for plt.legend(). Defaults to None.
93+
band_names (list, optional): List of band names to plot. Defaults to None (uses ugrizy).
94+
plot_kwargs (dict, optional): Additional keyword arguments for plt.errorbar(). Defaults to None.
95+
filter_colors (dict, optional): Mapping of band names to colors.
96+
Defaults to plot_filter_colors_white_background.
97+
filter_symbols (dict, optional): Mapping of band names to marker symbols.
98+
Defaults to plot_symbols.
99+
filter_linestyles (dict, optional): Mapping of band names to line styles.
100+
Defaults to plot_linestyles_none.
101+
period (float, optional): If provided, folds the time axis by this period (in days).
102+
Defaults to None.
103+
num_periods (int): Used to plot multiple full periods. Defaults to 1 (single period).
104+
period_mjd0 (float, optional): The time of the start of the phase-folded light curve.
105+
If not provided, we use the earliest ``midpointMjdTai`` value.
106+
107+
Returns:
108+
None
109+
"""
110+
# Let's first set values to defaults if they're not specified in kwargs.
111+
if plot_kwargs is None:
112+
plot_kwargs = {}
113+
if filter_colors is None:
114+
filter_colors = plot_filter_colors_white_background
115+
if filter_symbols is None:
116+
filter_symbols = plot_symbols
117+
if filter_linestyles is None:
118+
filter_linestyles = plot_linestyles_none
119+
120+
if legend_kwargs is None:
121+
legend_kwargs = {}
122+
if band_names is None:
123+
band_names = band_names_ugrizy
124+
125+
is_mag = flux_field is None
126+
brightness_field = flux_field or mag_field
127+
brightness_err_field = f"{brightness_field}Err"
128+
if period_mjd0 is None:
129+
period_mjd0 = lc["midpointMjdTai"].min()
130+
131+
# Actually do the plot
132+
for band in band_names:
133+
data = lc.query(f"band == '{band}'")
134+
if len(data) == 0:
135+
continue
136+
x_axis = data["midpointMjdTai"]
137+
if period is not None:
138+
x_axis = (x_axis - period_mjd0) / period % num_periods
139+
plt.errorbar(
140+
x_axis,
141+
data[brightness_field],
142+
yerr=data[brightness_err_field],
143+
label=band,
144+
linestyle=filter_linestyles[band],
145+
fmt=filter_symbols[band],
146+
color=filter_colors[band],
147+
**plot_kwargs,
148+
)
149+
150+
if is_mag:
151+
plt.gca().invert_yaxis()
152+
153+
if period is None:
154+
plt.xlabel("MJD")
155+
else:
156+
plt.xlabel("phase")
157+
plt.xlim([0, num_periods])
158+
title = title + f" (period = {period} d)"
159+
160+
plt.ylabel(brightness_field)
161+
plt.title(title)
162+
plt.legend(**legend_kwargs)
12.6 MB
Binary file not shown.
23.2 KB
Binary file not shown.
43.5 KB
Binary file not shown.
56.3 KB
Binary file not shown.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#HATS catalog
2+
obs_collection=mock_dp1_1000
3+
dataproduct_type=object
4+
hats_nrows=1000
5+
hats_col_ra=ra
6+
hats_col_dec=dec
7+
hats_npix_suffix=.parquet
8+
hats_skymap_order=8
9+
hats_max_rows=1000
10+
hats_builder=lsdb v0.6.4.dev2+gf79d1a04, hats v0.6.2
11+
hats_creation_date=2025-08-08T13\:53UTC
12+
hats_estsize=25358
13+
hats_release_date=2024-09-18
14+
hats_version=v0.1
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Norder,Npix
2+
0,0
6.01 MB
Binary file not shown.

0 commit comments

Comments
 (0)