diff --git a/Commissioning/101_lsstcam_visits_database.ipynb b/Commissioning/101_lsstcam_visits_database.ipynb
index b342f05..0114e0d 100644
--- a/Commissioning/101_lsstcam_visits_database.ipynb
+++ b/Commissioning/101_lsstcam_visits_database.ipynb
@@ -18,12 +18,12 @@
"\n",
"\n",
"\n",
- "For the Rubin Science Platform at data.lsst.cloud.
\n",
- "Container Size: Large
\n",
- "LSST Science Pipelines version: v29.2.0
\n",
- "Last verified to run: 2025-11-12
\n",
- "Repository: github.com/lsst/tutorial-notebooks
\n",
- "DOI: 10.11578/rubin/dc.20250909.20
"
+ "For the Rubin Science Platform at data.lsst.cloud.\\\n",
+ "Container Size: Large\\\n",
+ "LSST Science Pipelines version: v29.2.0\\\n",
+ "Last verified to run: 2026-01-28\\\n",
+ "Repository: github.com/lsst/tutorial-notebooks\\\n",
+ "DOI: 10.11578/rubin/dc.20250909.20"
]
},
{
@@ -1039,7 +1039,27 @@
"id": "99aa1d6b-4c85-4d41-aafb-0b1b5f7d8faa",
"metadata": {},
"source": [
- "Recreate the table above, but for the SV DDF, and include all field (do not restrict to fields with >50 visits)."
+ "Recreate the two tables above, but for the SV DDF, and include all fields (do not restrict to fields with >50 visits)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b862d38b-706d-48a6-a243-4c239f96ec13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "query = \"observation_reason.str.contains('ddf')\"\n",
+ "df_ddf = df.query(query).groupby(['observation_reason', 'band']).agg({'seq_num': 'count'})\n",
+ "df_ddf.rename({'seq_num': 'count'}, axis=1, inplace=True)\n",
+ "df_ddf = df_ddf.reset_index('band').pivot(columns=[\"band\"]).droplevel(0, axis=1)\n",
+ "df_ddf = df_ddf[['u', 'g', 'r', 'i', 'z', 'y']]\n",
+ "df_ddf['all'] = df_ddf.sum(axis=1)\n",
+ "df_ddf = df_ddf.query(\"all > 0\").sort_values('all')\n",
+ "table = tabulate(pd.DataFrame(df_ddf.round(0)), headers='keys')\n",
+ "table = table.replace('nan', ' 0')\n",
+ "print(table)\n",
+ "del query, df_ddf, table"
]
},
{
@@ -1222,6 +1242,58 @@
"Read more about they sky coverage for the SV wide-area survey on the Science Validation survey summary webpage ."
]
},
+ {
+ "cell_type": "markdown",
+ "id": "f40d0511-12bc-451f-832d-ff5eabffee03",
+ "metadata": {},
+ "source": [
+ "#### 5.1. Sky map for DDFs only\n",
+ "\n",
+ "Create a sky map for only the DDFs, which will be where alert production will start in early 2026."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e95d55ce-5a17-403a-a7ea-2bf48caa653d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "constraint = \"observation_reason like \\'%ddf%\\'\"\n",
+ "bundle = maf.MetricBundle(metric, slicer, constraint, run_name=run_name)\n",
+ "group = maf.MetricBundleGroup({'nvisits': bundle},\n",
+ " opsim_fname, out_dir=output_path)\n",
+ "group.run_all()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "113eccfe-9598-4ce9-8708-b50a1cbbc952",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ph = maf.PlotHandler(savefig=False, fig_format='png', thumbnail=False, dpi=270)\n",
+ "ph.set_metric_bundles([bundle])\n",
+ "ph.plot(plot_func=maf.plots.HealpixSkyMap(),\n",
+ " plot_dicts={'color_min': 20, 'color_max': 100, 'figsize': (6, 4),\n",
+ " 'labelsize': 'x-large', 'fontsize': 'x-large', 'extend': 'max',\n",
+ " 'title': 'Deep Drilling Field LSSTCam Visits as of 2025-09-30'})\n",
+ "plt.figtext(0.40, 0.62, 'XMM LSS', fontsize='large', fontweight='bold', color='white')\n",
+ "plt.figtext(0.36, 0.50, 'ECDFS', fontsize='large', fontweight='bold', color='white')\n",
+ "plt.figtext(0.36, 0.33, 'EDFS', fontsize='large', fontweight='bold', color='white')\n",
+ "plt.figtext(0.47, 0.43, 'ELAIS-S1', fontsize='large', fontweight='bold', color='white')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2a9aaa25-6d90-41c7-acaf-485ea7dead82",
+ "metadata": {},
+ "source": [
+ "> **Figure 7:** The locations of the four Deep Drilling Fields (DDFs), with their names labeled. See Figure 1 for the field central coordinates."
+ ]
+ },
{
"cell_type": "markdown",
"id": "135c0da0-4d13-4230-9abe-2add68bb1266",
diff --git a/Commissioning/102_rubin_schedule_viewer.ipynb b/Commissioning/102_rubin_schedule_viewer.ipynb
index bba9149..2c3f87c 100644
--- a/Commissioning/102_rubin_schedule_viewer.ipynb
+++ b/Commissioning/102_rubin_schedule_viewer.ipynb
@@ -18,10 +18,10 @@
"\n",
"\n",
"\n",
- "For the Rubin Science Platform at data.lsst.cloud.
\n",
- "Container Size: Large
\n",
- "LSST Science Pipelines version: v29.2.0
\n",
- "Last verified to run: 2025-12-04
\n",
+ "For the Rubin Science Platform at data.lsst.cloud.\\\n",
+ "Container Size: Large\\\n",
+ "LSST Science Pipelines version: v29.2.0\\\n",
+ "Last verified to run: 2025-01-28\\\n",
"Repository: [github.com/lsst/tutorial-notebooks](https://github.com/lsst/tutorial-notebooks)\\\n",
"DOI: [10.11578/rubin/dc.20250909.20](https://doi.org/10.11578/rubin/dc.20250909.20)"
]
@@ -88,28 +88,35 @@
"The ObsLocTAP data model (table schema) for the scheduled observations is defined in the `ivoa.obsplan` table -- Observation Locator \n",
"Table Access Protocol Version 1.0\n",
"\n",
- "The database contains 28 columns in total, but these are the key columns used in this tutorial.\n",
+ "The database contains 28 columns in total, and these are the key columns.\n",
"\n",
- "* `t_planning` : Time (MJD) when this observation has been added or modified into the planning log.\n",
- "* `target_name` : The name of the astronomical object observed, if any.\n",
- "* `obs_id` : The observation ID from the Camera.\n",
- "* `s_ra` : The Right Ascension of the visit or planned observation (degrees).\n",
- "* `s_dec` : The Declination of the visit or planned observation (degrees).\n",
- "* `s_fov` : The diameter (bounds) of the covered region.\n",
- "* `s_region` : Sky region covered by the data product (expressed in ICRS frame).\n",
- "* `s_resolution` : The spatial resolution of the data expressed as FWHM.\n",
"* `t_min` : The start time (MJD).\n",
"* `t_max` : The stop time (MJD).\n",
- "* `t_exptime` : The total exposure time = `t_max - t_min`.\n",
- "* `t_resolution` : Temporal resolution.\n",
- "* `facility_name` : Name of the facility used for this observation e.g Rubin Simonyi, AuxTel.\n",
- "* `instrument_name` : Name of the instrument used for this observation e.g LSSTCam, LSSTComCam.\n",
- "* `t_plan_exptime` : The planned or scheduled exposure time.\n",
+ "* `s_ra` : The Right Ascension of the visit or planned observation (deg).\n",
+ "* `s_dec` : The Declination of the visit or planned observation (deg).\n",
+ "* `em_min` : The filter minimum wavelength (m).\n",
+ "* `em_max` : The filter maximum wavelength (m).\n",
+ "* `target_name` : The name of the astronomical object observed, if any.\n",
+ "* `tracking_type` : One of the following values: Sidereal, Solar-system-object-tracking, Fixed-az-el-transit.\n",
"* `priority` : The Priority level { 0, 1, 2}. 0 = in the target queue as the next visit\n",
"(meaning its execution is highly likely), 1 = in the 1 hour look-ahead summit queue (meaning likely),\n",
"2 = 24 hour pre-night simulation, meaning it is not in the summit queue and has a high degree of uncertainty. \n",
+ "* `t_planning` : Time (MJD) when this observation has been added or modified into the planning log.\n",
"* `execution_status` : Execution status of the prediction: One of the following values: Planned, Scheduled, Unscheduled, Performed, Aborted.\n",
- "* `tracking_type` : One of the following values: Sidereal, Solar-system-object-tracking, Fixed-az-el-transit.\n",
+ "\n",
+ "Key columns that remained unpopulated as of the last update of this tutorial.\n",
+ "\n",
+ "* `s_region` : Sky region covered by the data product (expressed in ICRS frame).\n",
+ "* `obs_id` : The observation ID from the Camera (currently the same as `target_name`).\n",
+ "\n",
+ "These are also columns of interest, but are generally the same for most observations taken with LSSTCam.\n",
+ "\n",
+ "* `t_plan_exptime` : The planned or scheduled exposure time (s).\n",
+ "* `t_exptime` : The total exposure time = `t_max - t_min` (s).\n",
+ "* `s_fov` : The diameter (bounds) of the covered region (deg).\n",
+ "* `s_resolution` : The spatial resolution of the data expressed as FWHM (arcsec/pixel).\n",
+ "* `facility_name` : Name of the facility used for this observation e.g Rubin Simonyi, AuxTel.\n",
+ "* `instrument_name` : Name of the instrument used for this observation e.g LSSTCam, LSSTComCam.\n",
"\n",
"See DMTN-263 for a description of all fields in the schema."
]
@@ -155,6 +162,53 @@
"warnings.filterwarnings(\"ignore\")"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "cd2a8cab-f364-420d-80ec-3c9f99e47cf7",
+ "metadata": {},
+ "source": [
+ "### 1.4. Define functions\n",
+ "\n",
+ "Define a function to convert the `em_min` and `em_max` columns into the bandpass (filter) name."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "27684781-bdf6-4fb4-a57b-e8b510253375",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def em_min_max_to_band(em_min, em_max):\n",
+ " \"\"\"\n",
+ " Convert the wavelength minimum and maximum to band name.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " em_min: float\n",
+ " Wavelength minimum, in m.\n",
+ " em_max: float\n",
+ " Wavelength maximum, in m.\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " band: string\n",
+ " Band (filter) name.\n",
+ " \"\"\"\n",
+ "\n",
+ " band = None\n",
+ " band_dict = {'u': (2.95e-7, 4.00e-7), 'g': (4.00e-7, 5.55e-7),\n",
+ " 'r': (5.50e-7, 6.92e-7), 'i': (6.90e-7, 8.20e-7),\n",
+ " 'z': (8.15e-7, 9.25e-7), 'y': (9.20e-7, 11.1e-7)}\n",
+ " for b in band_dict.keys():\n",
+ " if em_min > band_dict[b][0] and em_max < band_dict[b][1]:\n",
+ " band = b\n",
+ " if band is None:\n",
+ " print(em_min, em_max, ' no band found')\n",
+ "\n",
+ " return band"
+ ]
+ },
{
"cell_type": "markdown",
"id": "d7cbe189-5a7c-4373-8fcb-076d661b0a6f",
@@ -196,7 +250,9 @@
"id": "9",
"metadata": {},
"source": [
- "Programmatically check the health of the static UI by executing the following cell, and assert that the static user interface service must be alive."
+ "Programmatically check the health of the static UI by executing the following cell, and assert that the static user interface service must be alive.\n",
+ "\n",
+ "> **Warning:** If `RemoteDisconnect` errors are returned, it means the service is temporarily unstable or unavailable, and to try again later."
]
},
{
@@ -206,7 +262,7 @@
"metadata": {},
"outputs": [],
"source": [
- "rubin_static_schedule_url = obsloctap_url + \"/static/viewer.html\"\n",
+ "rubin_static_schedule_url = obsloctap_url + \"/static/viewer.html\"\n",
"response = requests.get(rubin_static_schedule_url)\n",
"assert response.status_code == 200, f\"request failed with status {response.status_code}\"\n",
"print(f\"Rubin Schedule Viewer at {response.url} is alive.\")"
@@ -376,7 +432,57 @@
"id": "26",
"metadata": {},
"source": [
- "Note that the values in the \"Execution Status\" field are all \"Scheduled\"."
+ "Note that the values in the \"Execution Status\" field are all \"Scheduled\".\n",
+ "\n",
+ "#### 3.1.1. Planned DDF observations\n",
+ "\n",
+ "When alerts begin streaming in early 2026, template images will only exist for the DDFs, and thus alerts will only stream in the DDFs.\n",
+ "\n",
+ "Print the number of planned observations per DDF in the next 24h, and in which filters the observations are planned.\n",
+ "\n",
+ "First, add a column for the band (filter), converted from the `em_min` and `em_max` columns."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6769ff38-6b03-4649-9f39-01c475a9e478",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "em_min = forward_24h_schedule['em_min'].values\n",
+ "em_max = forward_24h_schedule['em_max'].values\n",
+ "temp = []\n",
+ "for i in range(len(forward_24h_schedule)):\n",
+ " temp.append(em_min_max_to_band(em_min[i], em_max[i]))\n",
+ "forward_24h_schedule['band'] = temp\n",
+ "del temp"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4148b3ff-9173-484a-991b-495ee6d25b95",
+ "metadata": {},
+ "source": [
+ "Define the names of the DDF fields, in the format of the `target_name` column.\n",
+ "For each field, sum the number of planned observations and print the unique filters for those observations."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fec6e949-a299-4eae-b4b4-f15da82c9e16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ddf_names = ['ddf_cosmos', 'ddf_ecdfs', 'ddf_elaiss1',\n",
+ " 'ddf_edfs_a', 'ddf_edfs_b', 'ddf_xmm_lss']\n",
+ "\n",
+ "for ddf_name in ddf_names:\n",
+ " temp = forward_24h_schedule.query(\"target_name.str.contains(@ddf_name)\")\n",
+ " band_list = \"\".join(str(value) for value in np.unique(temp['band']))\n",
+ " print('%-12s %3i bands: %-15s' % (ddf_name, len(temp), band_list))\n",
+ " del temp, band_list"
]
},
{
@@ -650,9 +756,9 @@
"metadata": {},
"outputs": [],
"source": [
- "print(f\"Min gap: {np.min(obs_visit_gap):.2f}\")\n",
- "print(f\"Max gap: {np.max(obs_visit_gap):.2f}\")\n",
- "print(f\"Mean gap: {np.mean(obs_visit_gap):.2f}\")"
+ "print(f\"Min gap: {np.min(obs_visit_gap): .2f}\")\n",
+ "print(f\"Max gap: {np.max(obs_visit_gap): .2f}\")\n",
+ "print(f\"Mean gap: {np.mean(obs_visit_gap): .2f}\")"
]
},
{