|
22 | 22 | "Data Release: <a href=\"https://dp1.lsst.io/\">Data Preview 1</a> <br>\n", |
23 | 23 | "Container Size: large <br>\n", |
24 | 24 | "LSST Science Pipelines version: r29.2.0 <br>\n", |
25 | | - "Last verified to run: 2026-01-31 <br>\n", |
| 25 | + "Last verified to run: 2026-02-10 <br>\n", |
26 | 26 | "Repository: <a href=\"https://github.com/lsst/tutorial-notebooks\">github.com/lsst/tutorial-notebooks</a> <br>" |
27 | 27 | ] |
28 | 28 | }, |
|
33 | 33 | "source": [ |
34 | 34 | "**Learning objective:** An overview of candidate transient (Ia Supernovae) identification in DP1.\n", |
35 | 35 | "\n", |
36 | | - "**LSST data products:** `DiaObject`, `ForcedSourceOnDiaObject`, `Visit`, `visit_image`, `template_coadd`, `difference_image`\n", |
| 36 | + "**LSST data products:** `DiaObject`, `Visit`, `visit_image`, `template_coadd`, `difference_image`\n", |
37 | 37 | "\n", |
38 | | - "**Packages:** `matplotlib`, `numpy`, `lsst.rsp`,`lsst.afw`, `lsst.geom`, `lsst.resources`, `lsst.utils.plotting`, `pyvo.dal.adhoc`\n", |
| 38 | + "**Packages:** `matplotlib`, `numpy`, `lsst.rsp`,`lsst.afw`, `lsst.geom`, `lsst.resources`, `lsst.utils.plotting`, `pyvo.dal.adhoc`, `reproject`\n", |
39 | 39 | "\n", |
40 | 40 | "**Credit:**\n", |
41 | 41 | "Originally developed by the Rubin Community Science team with feedback from Eric Bellm. This notebook also utilizes a transient detection from LSSTComCam first identified by Dan Taranu.\n", |
|
56 | 56 | "source": [ |
57 | 57 | "## 1. Introduction\n", |
58 | 58 | "\n", |
59 | | - "This notebook demonstrates how to use the light curve statistics in the DiaObject table to identify candidate transients. The specific case in this notebook is for Ia Supernova candidates.\n", |
| 59 | + "This notebook demonstrates how to produce bulk image cutouts using the Rubin cutout service.\n", |
60 | 60 | "\n", |
61 | | - "**Related tutorials**: There are 200-level tutorials on `difference_images` as well as the `DiaSource`, `DiaObject` and `ForcedSourceOnDiaObject` catalogs. Use of the image cutout service is covered in the 100-level tutorials. There is another notebook in this 306 series (306.1) that presents how to make a light curve of an extragalactic transient." |
| 61 | + "**Related tutorials**: This is the second of two 100-level tutorials demonstrating use of the image cutout service. Tutorial notebook 103.4 demonstrates the return of cutouts of Rubin LSST image type ExposureF and MaskedImageF." |
62 | 62 | ] |
63 | 63 | }, |
64 | 64 | { |
|
82 | 82 | "\n", |
83 | 83 | "From the `lsst` package, import modules for accessing the Table Access Protocol (TAP) service, image display functions, and the Simple Image Access (SIA) service from the LSST Science Pipelines (<a href=\"https://pipelines.lsst.io/\">pipelines.lsst.io</a>).\n", |
84 | 84 | "\n", |
85 | | - "Functions from `pyvo` are imported to perform and parse results from Datalink and SODA queries. This is used to obtain image products cutouts from the SIA service." |
| 85 | + "Functions from `pyvo` are imported to perform and parse results from Datalink and SODA queries. This is used to obtain image products cutouts from the SIA service.\n", |
| 86 | + "\n" |
86 | 87 | ] |
87 | 88 | }, |
88 | 89 | { |
|
93 | 94 | "outputs": [], |
94 | 95 | "source": [ |
95 | 96 | "import matplotlib.pyplot as plt\n", |
| 97 | + "import math\n", |
| 98 | + "\n", |
96 | 99 | "import numpy as np\n", |
97 | 100 | "from astropy import units as u\n", |
98 | 101 | "\n", |
|
104 | 107 | " get_multiband_plot_symbols)\n", |
105 | 108 | "\n", |
106 | 109 | "import lsst.afw.display as afwDisplay\n", |
107 | | - "from lsst.afw.image import ExposureF, ImageF\n", |
108 | | - "from lsst.afw.math import Warper, WarperConfig\n", |
| 110 | + "from lsst.afw.image import ImageF\n", |
109 | 111 | "from lsst.afw.fits import MemFileManager\n", |
110 | 112 | "import lsst.geom as geom\n", |
111 | 113 | "import lsst.resources\n", |
|
115 | 117 | "from astropy.wcs import WCS\n", |
116 | 118 | "from astropy.io import fits\n", |
117 | 119 | "import io\n", |
118 | | - "import tempfile\n", |
119 | 120 | "import getpass\n", |
120 | 121 | "import glob\n", |
| 122 | + "import os\n", |
121 | 123 | "\n", |
122 | 124 | "from reproject import reproject_interp\n", |
123 | 125 | "\n", |
|
351 | 353 | " return ImageF(mem), hdul" |
352 | 354 | ] |
353 | 355 | }, |
| 356 | + { |
| 357 | + "cell_type": "code", |
| 358 | + "execution_count": null, |
| 359 | + "id": "413fc23e-6c5e-47b6-997e-45d704d709a8", |
| 360 | + "metadata": {}, |
| 361 | + "outputs": [], |
| 362 | + "source": [ |
| 363 | + "def make_subplot_grid(n_subplots, figsize_per_plot=(4, 3)):\n", |
| 364 | + " \"\"\"\n", |
| 365 | + " Create an optimal grid of subplots for n_subplots.\n", |
| 366 | + "\n", |
| 367 | + " Returns\n", |
| 368 | + " -------\n", |
| 369 | + " fig : matplotlib.figure.Figure\n", |
| 370 | + " axes : list of matplotlib.axes.Axes\n", |
| 371 | + " \"\"\"\n", |
| 372 | + " n_cols = math.ceil(math.sqrt(n_subplots))\n", |
| 373 | + " n_rows = math.ceil(n_subplots / n_cols)\n", |
| 374 | + "\n", |
| 375 | + " figsize = (figsize_per_plot[0] * n_cols,\n", |
| 376 | + " figsize_per_plot[1] * n_rows)\n", |
| 377 | + "\n", |
| 378 | + " fig, axes = plt.subplots(n_rows, n_cols, figsize=figsize)\n", |
| 379 | + " axes = axes.flatten() if n_subplots > 1 else [axes]\n", |
| 380 | + "\n", |
| 381 | + " return fig, axes[:n_subplots]" |
| 382 | + ] |
| 383 | + }, |
354 | 384 | { |
355 | 385 | "cell_type": "markdown", |
356 | 386 | "id": "b1091fba-dbf4-4bdf-9970-f1a69951a4f2", |
|
373 | 403 | "metadata": {}, |
374 | 404 | "outputs": [], |
375 | 405 | "source": [ |
376 | | - "SNcandID = 611255759837069401\n", |
377 | | - "#ra = DiaObjs[DiaObjs['diaObjectId'] == SNcandID]['ra'][0]\n", |
378 | | - "#dec = DiaObjs[DiaObjs['diaObjectId'] == SNcandID]['dec'][0]\n", |
379 | | - "ra = 53.124767650110215 \n", |
| 406 | + "#SNcandID = 611255759837069401\n", |
| 407 | + "ra = 53.124767650110215\n", |
380 | 408 | "dec = -27.739814591611168\n", |
381 | 409 | "spherePoint = lsst.geom.SpherePoint(ra*geom.degrees, dec*geom.degrees)" |
382 | 410 | ] |
|
505 | 533 | "outputs": [], |
506 | 534 | "source": [ |
507 | 535 | "print('begin date:', scitab['t_max'][0], difftab['t_max'][0])\n", |
508 | | - "print('end date:', scitab['t_max'][len(scitab['t_max'])-1])#, difftab['t_max'][0])\n", |
509 | | - "print('number of visits:', len(scitab['t_max']))\n" |
| 536 | + "print('end date:', scitab['t_max'][len(scitab['t_max'])-1])\n", |
| 537 | + "print('number of visits:', len(scitab['t_max']))" |
510 | 538 | ] |
511 | 539 | }, |
512 | 540 | { |
|
550 | 578 | "metadata": {}, |
551 | 579 | "outputs": [], |
552 | 580 | "source": [ |
553 | | - "#stamps could be smaller? \n", |
554 | | - "\n", |
555 | | - "fov = 0.003\n", |
| 581 | + "fov = 0.002\n", |
556 | 582 | "sci, scihdul = get_cutout(dl_result_sci, spherePoint, get_pyvo_auth(), fov)\n", |
557 | 583 | "ref, refhdul = get_cutout(dl_result_ref, spherePoint, get_pyvo_auth(), fov)\n", |
558 | 584 | "diff, diffhdul = get_cutout(dl_result_diff, spherePoint, get_pyvo_auth(), fov)" |
|
634 | 660 | "\n", |
635 | 661 | "ref_primary_header = refhdul[0].header\n", |
636 | 662 | "ref_hdu = refhdul[1]\n", |
637 | | - "ref_header =refhdul[1].header\n", |
| 663 | + "ref_header = refhdul[1].header\n", |
638 | 664 | "refdata = refhdul[1].data\n", |
639 | 665 | "refwcs = WCS(refhdul[1].header)\n" |
640 | 666 | ] |
641 | 667 | }, |
| 668 | + { |
| 669 | + "cell_type": "markdown", |
| 670 | + "id": "02974977-001b-467e-ae0d-dc44f105872c", |
| 671 | + "metadata": {}, |
| 672 | + "source": [ |
| 673 | + "Use the `reproject_interp` function to put the science visit image onto the WCS of the template image." |
| 674 | + ] |
| 675 | + }, |
| 676 | + { |
| 677 | + "cell_type": "code", |
| 678 | + "execution_count": null, |
| 679 | + "id": "635013a0-e962-4958-bb09-007ac1cb169e", |
| 680 | + "metadata": {}, |
| 681 | + "outputs": [], |
| 682 | + "source": [ |
| 683 | + "reproj_scidata, footprint = reproject_interp((scidata, sciwcs), refwcs)" |
| 684 | + ] |
| 685 | + }, |
| 686 | + { |
| 687 | + "cell_type": "markdown", |
| 688 | + "id": "6b3360a9-ccc6-47bb-bc45-b87f208dacda", |
| 689 | + "metadata": {}, |
| 690 | + "source": [ |
| 691 | + "Plot the reprojected science visit image together with the template image to compare." |
| 692 | + ] |
| 693 | + }, |
642 | 694 | { |
643 | 695 | "cell_type": "code", |
644 | 696 | "execution_count": null, |
645 | 697 | "id": "d9734ade-5848-4e44-8e38-ea70aebd6a47", |
646 | 698 | "metadata": {}, |
647 | 699 | "outputs": [], |
648 | 700 | "source": [ |
649 | | - "\n", |
650 | | - "reproj_scidata, footprint = reproject_interp((scidata, sciwcs), refwcs)\n", |
651 | | - "\n", |
652 | | - "ax1 = plt.subplot(1,2,1, projection=WCS(ref_hdu.header))\n", |
| 701 | + "ax1 = plt.subplot(1, 2, 1, projection=WCS(ref_hdu.header))\n", |
653 | 702 | "ax1.imshow(reproj_scidata, origin='lower', vmin=np.nanpercentile(reproj_scidata, 1),\n", |
654 | 703 | " vmax=np.nanpercentile(reproj_scidata, 99))\n", |
655 | 704 | "ax1.coords['ra'].set_axislabel('Right Ascension')\n", |
656 | 705 | "ax1.coords['dec'].set_axislabel('Declination')\n", |
657 | 706 | "ax1.set_title('Reprojected Visit Image')\n", |
658 | 707 | "\n", |
659 | | - "ax2 = plt.subplot(1,2,2, projection=WCS(ref_hdu.header))\n", |
660 | | - "ax2.imshow(refdata, origin='lower',vmin=np.nanpercentile(refdata, 1), vmax=np.nanpercentile(refdata, 99))\n", |
| 708 | + "ax2 = plt.subplot(1, 2, 2, projection=WCS(ref_hdu.header))\n", |
| 709 | + "ax2.imshow(refdata, origin='lower', vmin=np.nanpercentile(refdata, 1),\n", |
| 710 | + " vmax=np.nanpercentile(refdata, 99))\n", |
661 | 711 | "ax2.coords['ra'].set_axislabel('Right Ascension')\n", |
662 | 712 | "ax2.coords['dec'].set_axislabel('Declination')\n", |
663 | 713 | "ax2.coords['dec'].set_axislabel_position('r')\n", |
|
683 | 733 | "Bulk image cutouts will be a key visualization tool for DIA objects. Below, demonstrate how to retrieve (and save), and display many image cutouts." |
684 | 734 | ] |
685 | 735 | }, |
686 | | - { |
687 | | - "cell_type": "code", |
688 | | - "execution_count": null, |
689 | | - "id": "413fc23e-6c5e-47b6-997e-45d704d709a8", |
690 | | - "metadata": {}, |
691 | | - "outputs": [], |
692 | | - "source": [ |
693 | | - "import math\n", |
694 | | - "import matplotlib.pyplot as plt\n", |
695 | | - "\n", |
696 | | - "def make_subplot_grid(n_subplots, figsize_per_plot=(4, 3)):\n", |
697 | | - " \"\"\"\n", |
698 | | - " Create an optimal grid of subplots for n_subplots.\n", |
699 | | - "\n", |
700 | | - " Returns\n", |
701 | | - " -------\n", |
702 | | - " fig : matplotlib.figure.Figure\n", |
703 | | - " axes : list of matplotlib.axes.Axes\n", |
704 | | - " \"\"\"\n", |
705 | | - " n_cols = math.ceil(math.sqrt(n_subplots))\n", |
706 | | - " n_rows = math.ceil(n_subplots / n_cols)\n", |
707 | | - "\n", |
708 | | - " figsize = (figsize_per_plot[0] * n_cols,\n", |
709 | | - " figsize_per_plot[1] * n_rows)\n", |
710 | | - "\n", |
711 | | - " fig, axes = plt.subplots(n_rows, n_cols, figsize=figsize)\n", |
712 | | - " axes = axes.flatten() if n_subplots > 1 else [axes]\n", |
713 | | - "\n", |
714 | | - " # Hide unused axes\n", |
715 | | - " for ax in axes[n_subplots:]:\n", |
716 | | - " ax.set_visible(False)\n", |
717 | | - "\n", |
718 | | - " return fig, axes[:n_subplots]" |
719 | | - ] |
720 | | - }, |
721 | 736 | { |
722 | 737 | "cell_type": "code", |
723 | 738 | "execution_count": null, |
|
734 | 749 | " j = i + 5\n", |
735 | 750 | " ax.set_title(f\"MJD {np.round(scitab['t_max'][j], 4)}\")\n", |
736 | 751 | "\n", |
737 | | - " dl_result_sci = DatalinkResults.from_result_url(scitab['access_url'][j], session=get_pyvo_auth())\n", |
738 | | - " #print(dl_result_sci)\n", |
| 752 | + " dl_result_sci = DatalinkResults.from_result_url(scitab['access_url'][j],\n", |
| 753 | + " session=get_pyvo_auth())\n", |
| 754 | + "\n", |
739 | 755 | " sci, scihdul = get_cutout(dl_result_sci, spherePoint, get_pyvo_auth(), fov)\n", |
740 | 756 | " sci_hdu = scihdul[1]\n", |
741 | 757 | " sci_header = scihdul[1].header\n", |
742 | 758 | " scidata = scihdul[1].data\n", |
743 | 759 | " sciwcs = WCS(scihdul[1].header)\n", |
744 | 760 | " reproj_scidata, footprint = reproject_interp((scidata, sciwcs), refwcs)\n", |
745 | 761 | "\n", |
746 | | - " ax.imshow(reproj_scidata, origin='lower', vmin=np.nanpercentile(reproj_scidata, 1), vmax=np.nanpercentile(reproj_scidata, 99))\n", |
747 | | - "\n", |
| 762 | + " ax.imshow(reproj_scidata, origin='lower', vmin=np.nanpercentile(reproj_scidata, 1),\n", |
| 763 | + " vmax=np.nanpercentile(reproj_scidata, 99))\n", |
748 | 764 | "\n", |
749 | 765 | " #figname = os.path.join(tempdir, 'cutout_' + str(i) + '.png')\n", |
750 | 766 | " #if os.path.isfile(figname):\n", |
751 | 767 | " # os.remove(figname)\n", |
752 | 768 | " #plt.savefig(figname)\n", |
753 | 769 | "\n", |
754 | | - "\n", |
755 | 770 | "plt.tight_layout()\n", |
756 | | - "plt.show()\n", |
757 | | - "\n", |
758 | | - "#for i in range(len(num_visits)):\n", |
759 | | - "\n", |
760 | | - "# " |
| 771 | + "plt.show()" |
761 | 772 | ] |
762 | 773 | }, |
763 | 774 | { |
|
787 | 798 | "outputs": [], |
788 | 799 | "source": [ |
789 | 800 | "for i in range(num_visits):\n", |
790 | | - " #ax.plot([0, 1, 2], [i, i + 1, i + 2])\n", |
791 | 801 | " j = i #+ 5\n", |
792 | 802 | " plt.title(f\"MJD {np.round(scitab['t_max'][j], 4)}\")\n", |
793 | 803 | "\n", |
794 | | - " dl_result_sci = DatalinkResults.from_result_url(scitab['access_url'][j], session=get_pyvo_auth())\n", |
795 | | - " #print(dl_result_sci)\n", |
| 804 | + " dl_result_sci = DatalinkResults.from_result_url(scitab['access_url'][j],\n", |
| 805 | + " session=get_pyvo_auth())\n", |
| 806 | + "\n", |
796 | 807 | " sci, scihdul = get_cutout(dl_result_sci, spherePoint, get_pyvo_auth(), fov)\n", |
797 | 808 | " sci_hdu = scihdul[1]\n", |
798 | 809 | " sci_header = scihdul[1].header\n", |
799 | 810 | " scidata = scihdul[1].data\n", |
800 | 811 | " sciwcs = WCS(scihdul[1].header)\n", |
801 | 812 | " reproj_scidata, footprint = reproject_interp((scidata, sciwcs), refwcs)\n", |
802 | 813 | "\n", |
803 | | - " plt.imshow(reproj_scidata, origin='lower', vmin=np.nanpercentile(reproj_scidata, 1), vmax=np.nanpercentile(reproj_scidata, 99))\n", |
804 | | - "\n", |
| 814 | + " plt.imshow(reproj_scidata, origin='lower', vmin=np.nanpercentile(reproj_scidata, 1),\n", |
| 815 | + " vmax=np.nanpercentile(reproj_scidata, 99))\n", |
805 | 816 | "\n", |
806 | 817 | " figname = os.path.join(tempdir, 'cutout_' + str(i) + '.png')\n", |
807 | 818 | " if os.path.isfile(figname):\n", |
808 | 819 | " os.remove(figname)\n", |
809 | 820 | " plt.savefig(figname)\n", |
810 | 821 | "\n", |
811 | | - "\n", |
812 | 822 | "#plt.tight_layout()\n", |
813 | 823 | "#plt.show()" |
814 | 824 | ] |
|
0 commit comments