Skip to content

Commit 4f7b18e

Browse files
authored
Merge pull request #39 from lsst/u/jcarlin/fsodo_300_fix
Update queries in lightcurve NBs
2 parents 9dd1033 + 8b992b7 commit 4f7b18e

3 files changed

Lines changed: 329 additions & 88 deletions

File tree

DP1/300_Science_Demos/305_Galactic_variables_and_transients/305_1_Variable_star_light_curves.ipynb

Lines changed: 120 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"For the Rubin Science Platform at data.lsst.cloud. <br>\n",
1919
"Data Release: <a href=\"https://dp1.lsst.io/\">Data Preview 1</a> <br>\n",
2020
"Container Size: large <br>\n",
21-
"LSST Science Pipelines version: Release r29.1.1 <br>\n",
21+
"LSST Science Pipelines version: r29.1.1 <br>\n",
2222
"Last verified to run: 2025-06-20 <br>\n",
2323
"Repository: <a href=\"https://github.com/lsst/tutorial-notebooks\">github.com/lsst/tutorial-notebooks</a> <br>"
2424
]
@@ -30,7 +30,7 @@
3030
"source": [
3131
"**Learning objective:** Learn how to extract and plot a light curve for a variable star from DP1.\n",
3232
"\n",
33-
"**LSST data products:** `ForcedSourceOnDiaObject`, `Visit`\n",
33+
"**LSST data products:** `ForcedSourceOnDiaObject`, `DiaObject`, `Visit`\n",
3434
"\n",
3535
"**Packages:** `matplotlib`, `numpy`, `lsst.rsp`, `lsst.utils.plotting`\n",
3636
"\n",
@@ -156,13 +156,15 @@
156156
"\n",
157157
"The units used to plot the light curve are in flux (nJy) and not magnitudes since the negative flux measurements would be omitted when converting to magnitudes.\n",
158158
"\n",
159+
"### 2.1 Look up diaObjectId from coordinates\n",
160+
"\n",
159161
"The first step to obtain light curve data is to define the coordinates (ra and dec) of a variable star captured in DP1: Gaia DR3 2912281258855051520."
160162
]
161163
},
162164
{
163165
"cell_type": "code",
164166
"execution_count": null,
165-
"id": "35077a54-59bd-44fa-9d31-114e3ddbd578",
167+
"id": "2b4fc159-bca1-40e8-b9b1-58b39a151bf8",
166168
"metadata": {},
167169
"outputs": [],
168170
"source": [
@@ -172,7 +174,7 @@
172174
},
173175
{
174176
"cell_type": "markdown",
175-
"id": "1f486e43-cbbe-4cab-b131-27eadc69c3b5",
177+
"id": "2d09a784-726c-4723-9df6-2f6ad99f6396",
176178
"metadata": {},
177179
"source": [
178180
"Define a 0.5 arcsecond search radius, and convert it to degrees."
@@ -181,7 +183,7 @@
181183
{
182184
"cell_type": "code",
183185
"execution_count": null,
184-
"id": "fe86ad87-b4ee-45cc-ad6c-71d8537c249e",
186+
"id": "29a7fea7-0329-419d-af1f-fbd9b5e9eb4f",
185187
"metadata": {},
186188
"outputs": [],
187189
"source": [
@@ -190,31 +192,105 @@
190192
},
191193
{
192194
"cell_type": "markdown",
193-
"id": "3154ec3a-cd86-45ad-b215-0946624902b7",
195+
"id": "ba3dc2e2-aa27-49bb-a4de-446538973955",
196+
"metadata": {},
197+
"source": [
198+
"Search at this position in the `DiaObject` table to retrieve the `diaObjectId` of the corresponding object."
199+
]
200+
},
201+
{
202+
"cell_type": "code",
203+
"execution_count": null,
204+
"id": "11e3579b-6812-479a-916b-fdad65e01baa",
205+
"metadata": {},
206+
"outputs": [],
207+
"source": [
208+
"query = \"SELECT ra, dec, diaObjectId \"\\\n",
209+
" \"FROM dp1.DiaObject \"\\\n",
210+
" \"WHERE CONTAINS(POINT('ICRS', ra, dec), \"\\\n",
211+
" \"CIRCLE('ICRS', \" + str(ra_var) + \", \"\\\n",
212+
" + str(dec_var) + \", \" + str(search_rad) + \")) = 1\"\n",
213+
"print(query)"
214+
]
215+
},
216+
{
217+
"cell_type": "code",
218+
"execution_count": null,
219+
"id": "08a4d843-d206-4f35-b635-e4f9253603d7",
220+
"metadata": {},
221+
"outputs": [],
222+
"source": [
223+
"job = service.submit_job(query)\n",
224+
"job.run()\n",
225+
"job.wait(phases=['COMPLETED', 'ERROR'])\n",
226+
"print('Job phase is', job.phase)\n",
227+
"if job.phase == 'ERROR':\n",
228+
" job.raise_if_error()"
229+
]
230+
},
231+
{
232+
"cell_type": "markdown",
233+
"id": "f14304ef-f1b2-4d2e-9b2f-c8099a592cc8",
234+
"metadata": {
235+
"execution": {
236+
"iopub.execute_input": "2025-06-30T22:25:25.363571Z",
237+
"iopub.status.busy": "2025-06-30T22:25:25.362713Z",
238+
"iopub.status.idle": "2025-06-30T22:25:25.368671Z",
239+
"shell.execute_reply": "2025-06-30T22:25:25.367868Z",
240+
"shell.execute_reply.started": "2025-06-30T22:25:25.363544Z"
241+
}
242+
},
243+
"source": [
244+
"Fetch the results of the TAP search in table form and print the unique entries for `diaObjectId` in the output table."
245+
]
246+
},
247+
{
248+
"cell_type": "code",
249+
"execution_count": null,
250+
"id": "9b7285dd-4b63-4482-baf0-8f63650f8834",
251+
"metadata": {},
252+
"outputs": [],
253+
"source": [
254+
"assert job.phase == 'COMPLETED'\n",
255+
"DiaObj = job.fetch_result().to_table()\n",
256+
"print(np.unique(DiaObj['diaObjectId']))"
257+
]
258+
},
259+
{
260+
"cell_type": "markdown",
261+
"id": "4f3fcea5-957d-4984-8f93-e49e1970e48b",
194262
"metadata": {},
195263
"source": [
196-
"Perform a TAP search on the coordinates of the transient in the `ForcedSourceOnDiaObject` table.\n",
264+
"### 2.2. Search based on diaObjectId\n",
197265
"\n",
198-
"Use a table JOIN with the `Visit` table to extract visit timing info (`expMidptMJD`) for each entry in the `ForcedSourceOnDiaObject`."
266+
"Provide this `diaObjectId` as a constraint to a TAP query to obtain the time series from `ForcedSourceOnDiaObject`. The use of an ID in this manner is always the recommended way to access data from a ForcedSource table."
199267
]
200268
},
201269
{
202270
"cell_type": "code",
203271
"execution_count": null,
204-
"id": "aee30c7f-38cf-4637-a7e9-dd476a69ddbc",
272+
"id": "0ca36902-76c6-4acd-a02b-c7e609f2cb82",
205273
"metadata": {},
206274
"outputs": [],
207275
"source": [
208-
"query = \"SELECT fsodo.diaObjectId, fsodo.coord_ra, fsodo.coord_dec, \"\\\n",
209-
" \"fsodo.visit, fsodo.detector, fsodo.band, \"\\\n",
276+
"DiaObjID = DiaObj['diaObjectId'][0]"
277+
]
278+
},
279+
{
280+
"cell_type": "code",
281+
"execution_count": null,
282+
"id": "3fb7afdc-9709-4d8e-a3e6-fa46075fe0ef",
283+
"metadata": {},
284+
"outputs": [],
285+
"source": [
286+
"query = \"SELECT fsodo.coord_ra, fsodo.coord_dec, \"\\\n",
287+
" \"fsodo.diaObjectId, fsodo.visit, fsodo.band, \"\\\n",
210288
" \"fsodo.psfDiffFlux, fsodo.psfDiffFluxErr, \"\\\n",
211289
" \"fsodo.psfFlux as psfFlux, fsodo.psfFluxErr, \"\\\n",
212290
" \"vis.expMidptMJD \"\\\n",
213291
" \"FROM dp1.ForcedSourceOnDiaObject as fsodo \"\\\n",
214292
" \"JOIN dp1.Visit as vis ON vis.visit = fsodo.visit \"\\\n",
215-
" \"WHERE CONTAINS (POINT('ICRS', coord_ra, coord_dec), \"\\\n",
216-
" \"CIRCLE('ICRS', \" + str(ra_var) + \", \"\\\n",
217-
" + str(dec_var) + \", \" + str(search_rad) + \")) = 1 \"\n",
293+
" \"WHERE fsodo.diaObjectId = \"+str(DiaObjID)\n",
218294
"print(query)"
219295
]
220296
},
@@ -223,13 +299,13 @@
223299
"id": "600390ba-63e6-47b6-a91b-1c19a4f5ff87",
224300
"metadata": {},
225301
"source": [
226-
"Run the TAP query, then extract the results of the TAP search to an Astropy table."
302+
"Run the TAP query."
227303
]
228304
},
229305
{
230306
"cell_type": "code",
231307
"execution_count": null,
232-
"id": "8685e9ba-5206-4ab9-9317-4f581ace2144",
308+
"id": "fca45813-9e8f-4571-ac51-ca10dac2046a",
233309
"metadata": {},
234310
"outputs": [],
235311
"source": [
@@ -238,18 +314,27 @@
238314
"job.wait(phases=['COMPLETED', 'ERROR'])\n",
239315
"print('Job phase is', job.phase)\n",
240316
"if job.phase == 'ERROR':\n",
241-
" job.raise_if_error()\n",
242-
"assert job.phase == 'COMPLETED'"
317+
" job.raise_if_error()"
318+
]
319+
},
320+
{
321+
"cell_type": "markdown",
322+
"id": "24628f61-7888-4df3-a72e-d2b18c6963c8",
323+
"metadata": {},
324+
"source": [
325+
"Fetch the results of the TAP search in table form and print the number of rows."
243326
]
244327
},
245328
{
246329
"cell_type": "code",
247330
"execution_count": null,
248-
"id": "b60aec9d-54ff-43fb-bacf-4d498b453887",
331+
"id": "8685e9ba-5206-4ab9-9317-4f581ace2144",
249332
"metadata": {},
250333
"outputs": [],
251334
"source": [
252-
"forced_sources = job.fetch_result().to_table()"
335+
"assert job.phase == 'COMPLETED'\n",
336+
"forced_source = job.fetch_result().to_table()\n",
337+
"print(len(forced_source))"
253338
]
254339
},
255340
{
@@ -267,7 +352,7 @@
267352
"metadata": {},
268353
"outputs": [],
269354
"source": [
270-
"# forced_sources"
355+
"# forced_source"
271356
]
272357
},
273358
{
@@ -286,7 +371,7 @@
286371
"outputs": [],
287372
"source": [
288373
"for band in filter_names:\n",
289-
" print(f\"{band}: {np.sum((forced_sources['band'] == band))} visits\")"
374+
" print(f\"{band}: {np.sum((forced_source['band'] == band))} visits\")"
290375
]
291376
},
292377
{
@@ -312,11 +397,11 @@
312397
"fig.subplots_adjust(wspace=0, hspace=0)\n",
313398
"\n",
314399
"for band in filter_names:\n",
315-
" pickband = np.where(forced_sources['band'] == band)\n",
316-
" ax1.plot(forced_sources[pickband]['expMidptMJD'], forced_sources[pickband]['psfDiffFlux'],\n",
400+
" pickband = np.where(forced_source['band'] == band)\n",
401+
" ax1.plot(forced_source[pickband]['expMidptMJD'], forced_source[pickband]['psfDiffFlux'],\n",
317402
" marker=filter_symbols[band], color=filter_colors[band],\n",
318403
" label=f\"{band}\", markersize=7, linestyle='none', fillstyle='none')\n",
319-
" ax2.plot(forced_sources[pickband]['expMidptMJD'], forced_sources[pickband]['psfFlux'],\n",
404+
" ax2.plot(forced_source[pickband]['expMidptMJD'], forced_source[pickband]['psfFlux'],\n",
320405
" marker=filter_symbols[band], color=filter_colors[band], linestyle='none',\n",
321406
" markersize=7, fillstyle='none')\n",
322407
"\n",
@@ -374,10 +459,10 @@
374459
"metadata": {},
375460
"outputs": [],
376461
"source": [
377-
"pickr = np.where(forced_sources['band'] == 'r')\n",
378-
"ind_max = np.argmax(forced_sources['psfFlux'][pickr])\n",
379-
"t0 = forced_sources['expMidptMJD'][pickr][ind_max]\n",
380-
"mjd_norm = (forced_sources['expMidptMJD'] - t0) / period\n",
462+
"pickr = np.where(forced_source['band'] == 'r')\n",
463+
"ind_max = np.argmax(forced_source['psfFlux'][pickr])\n",
464+
"t0 = forced_source['expMidptMJD'][pickr][ind_max]\n",
465+
"mjd_norm = (forced_source['expMidptMJD'] - t0) / period\n",
381466
"phase = np.mod(mjd_norm, 1.0)"
382467
]
383468
},
@@ -400,12 +485,12 @@
400485
"fig.subplots_adjust(wspace=0, hspace=0)\n",
401486
"\n",
402487
"for band in filter_names:\n",
403-
" pickband = np.where((forced_sources['band'] == band)\n",
404-
" & (forced_sources['psfDiffFlux'] > -50000))\n",
405-
" ax1.plot(phase[pickband], forced_sources[pickband]['psfDiffFlux'],\n",
488+
" pickband = np.where((forced_source['band'] == band)\n",
489+
" & (forced_source['psfDiffFlux'] > -50000))\n",
490+
" ax1.plot(phase[pickband], forced_source[pickband]['psfDiffFlux'],\n",
406491
" marker=filter_symbols[band], color=filter_colors[band],\n",
407492
" label=f\"{band}\", markersize=7, linestyle='none', fillstyle='none')\n",
408-
" ax2.plot(phase[pickband], forced_sources[pickband]['psfFlux'],\n",
493+
" ax2.plot(phase[pickband], forced_source[pickband]['psfFlux'],\n",
409494
" marker=filter_symbols[band], color=filter_colors[band], linestyle='none',\n",
410495
" markersize=7, fillstyle='none')\n",
411496
"\n",
@@ -443,7 +528,7 @@
443528
"metadata": {},
444529
"outputs": [],
445530
"source": [
446-
"mag = forced_sources['psfFlux'].to(u.ABmag).value"
531+
"mag = forced_source['psfFlux'].to(u.ABmag).value"
447532
]
448533
},
449534
{
@@ -456,7 +541,7 @@
456541
"fig, ax = plt.subplots(1, 1, figsize=(7, 5))\n",
457542
"\n",
458543
"for band in filter_names:\n",
459-
" pickband = np.where(forced_sources['band'] == band)\n",
544+
" pickband = np.where(forced_source['band'] == band)\n",
460545
" ax.plot(phase[pickband], mag[pickband],\n",
461546
" marker=filter_symbols[band], color=filter_colors[band],\n",
462547
" label=f\"{band}\", markersize=7, linestyle='none', fillstyle='none')\n",

0 commit comments

Comments
 (0)