diff --git a/.github/workflows/ci_tests_run_notebooks.yml b/.github/workflows/ci_tests_run_notebooks.yml index 85876ef9..903c517c 100644 --- a/.github/workflows/ci_tests_run_notebooks.yml +++ b/.github/workflows/ci_tests_run_notebooks.yml @@ -46,4 +46,8 @@ jobs: run: python -m pip install --upgrade tox - name: Test with tox - run: tox ${{ matrix.toxargs }} -e ${{ matrix.toxenv }} -- ${{ matrix.toxposargs }} + run: | + # Workaround for OSX for https://jira.ipac.caltech.edu/browse/FIREFLY-1528 + bash -c 'if echo ${{ runner.os }} | grep -i macos; then echo tutorials/firefly >> ignore_testing; fi' + + tox ${{ matrix.toxargs }} -e ${{ matrix.toxenv }} -- ${{ matrix.toxposargs }} diff --git a/index.md b/index.md index 3c25e0e4..82e202aa 100644 --- a/index.md +++ b/index.md @@ -37,16 +37,19 @@ tutorials/cosmodc2/cosmoDC2_TAP_access.md ``` - + ## IRSA in the cloud diff --git a/tutorials/firefly/NEOWISE_light_curve_demo.md b/tutorials/firefly/NEOWISE_light_curve_demo.md new file mode 100644 index 00000000..d2cdf14d --- /dev/null +++ b/tutorials/firefly/NEOWISE_light_curve_demo.md @@ -0,0 +1,160 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.2 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + +# Finding Light Curves of Solar System Objects + +## Learning Goals + +By the end of this tutorial, you will: + +- Construct a TAP query to download the necessary data and visualize it via the web browser with an instantiated Firefly environment. +- Plot light curves from NEOWISE data using the Firefly Python API. +- Format cells containing tables, charts and images viewed in the client. +- Overlay a catalog of data onto a HiPS image. + ++++ + +## Introduction + +This tutorial demonstrates how to plot light curves from NEOWISE data while also flaunting the many useful capabilities of the Firefly Python API. Using the 'Known Solar System Object Possible Association List' catalog from the NEOWISE-R database, we can easily compose a light curve of the faint asteroid `558 Carmen` and show its observed positions in the sky solely through the `firefly_client` package. Minor planet light curves are important in determining their size, spectral class, rotation period and many other properties. + +Firefly is an astronomical data access and visualization written by Caltech/IPAC-IRSA. The visualization provides user with an integrated experience with brushing and linking capabilities among images, catalogs, and plots. Firefly is used in IRSA GUIs to query and visualize data from missions such as WISE, Spitzer, SOFIA, ZTF, PTF, etc. and a large number of highly-used contributed data products from a diverse set of astrophysics projects. + +The `firefly_client` package provides a lightweight client class that includes a Python interface to Firefly’s Javascript API. + +For documentation on the firefly client visit https://caltech-ipac.github.io/firefly_client/. + ++++ + +## Imports + +- *firefly_client FireflyClient* - Python API to Firefly for displaying tables, images and charts +- *firefly_client.plot* for visualizing the light curve in the client +- *astropy.utils.data* for downloading the catalog data via TAP query + +```{code-cell} ipython3 +from firefly_client import FireflyClient +import firefly_client.plot as ffplt +import astropy.utils.data +``` + +## Step 1 + +Instantiate the client via and view it in a different tab in the web browser. + +In this example, we use the IRSA Viewer - a public firefly server. The firefly server can also be run locally, e.g. via a Firefly Docker image obtained from https://hub.docker.com/r/ipac/firefly/tags/. + +```{code-cell} ipython3 +url = 'https://irsa.ipac.caltech.edu/irsaviewer' +# url='http://127.0.0.1:8080/firefly' # if you have firefly server running locally (preferably through docker) + +fc = FireflyClient.make_client(url) +ffplt.use_client(fc) +``` + +You can re-initizialize the viewer to return to a clean slate with [`reinit_viewer`](https://caltech-ipac.github.io/firefly_client/api/firefly_client.FireflyClient.html#firefly_client.FireflyClient.reinit_viewer). + +```{code-cell} ipython3 +# fc.reinit_viewer(); # The semi-colon suppresses the output of the method when ran +``` + +## Step 2 + +Setup the layout of viewer and TAP search the 'Known Solar System Object Possible Association List' catalog from the NEOWISE-R database. The specific target we are looking for is minor planet `558 Carmen`. We can query this target using a TAP search through IRSA; the `table_url` is broken down as follows: + +- We want to search the data through IRSA, which supports TAP querying, and we want it streamed directly to us via a synchronous search:
"https://irsa.ipac.caltech.edu/TAP/sync?"

+- Next, we want to structure query to only retrieve (558) Carmen data from the NEOWISE-R 'Known Solar System Object Possible Association List' catalog. The table name of the catalog can be found using [IRSAViewer](https://irsa.ipac.caltech.edu/irsaviewer/?__action=layout.showDropDown&view=MultiTableSearchCmd) and clicking the **VO TAP Search** tab and changing the 'Project' to **neowiser**. We query all columns of data and we search the target by its object id, which is its name, and use the 'like' condition to only write (558) with a wildcard:
"QUERY=SELECT+*+FROM+neowiser_p1ba_mch+AS+n+WHERE+n.objid+like+'(558)%'" + +Construction of the query can be found in the [`IRSA TAP documentation page`](https://irsa.ipac.caltech.edu/docs/program_interface/TAP.html). + +We first add a cell to the layout that will hold the table; this cell is shown at row = 0, col = 0, with width = 4, height = 2. Once the cell is created, we can request the necessary data from the catalog and display the data as a table using the [`show_table`](https://caltech-ipac.github.io/firefly_client/api/firefly_client.FireflyClient.html#firefly_client.FireflyClient.show_table) method. + +Alternatively, we can download data from the catalog using [`astropy.utils.data.download_file`](https://docs.astropy.org/en/stable/api/astropy.utils.data.download_file.html) and upload it to the Firefly client shown in the cell below the first method. + +```{code-cell} ipython3 +r = fc.add_cell(0, 0, 4, 2, 'tables', 'main') + +if r['success']: + table_url = ("https://irsa.ipac.caltech.edu/TAP/sync?QUERY=SELECT+*+FROM+neowiser_p1ba_mch+AS+n+WHERE+n.objid+like+'(558)%'") + fc.show_table(table_url, tbl_id='tableneo', title='558 Carmen NeoWise Catalog', page_size=50) +``` + +```{code-cell} ipython3 +# r = fc.add_cell(0, 0, 4, 2, 'tables', 'main') + +# if r['success']: +# table_url = ("https://irsa.ipac.caltech.edu/TAP/sync?QUERY=SELECT+*+FROM+neowiser_p1ba_mch+AS+n+WHERE+n.objid+like+'(558)%'") +# tablename = astropy.utils.data.download_file(table_url, timeout=120, cache=True) + +# file = fc.upload_file(tablename) +# fc.show_table(file, tbl_id='tableneo', title='558 Carmen Catalog', page_size=50) +``` + +## Step 3 + +After retrieving the data and displaying it in the client, we can now create a light curve by plotting the Modified Julian Date ('mjd') in the abscissa and the magnitude from band W1 ('w1mpro') in the ordinate. We also flip the ordinate to accurately display magnitude. + +```{code-cell} ipython3 +r = fc.add_cell(2, 0, 2, 2, 'plot-image', 'light-curve') +if r['success']: + status = fc.show_xyplot(tbl_id='tableneo', xCol='mjd', yCol='w1mpro', yOptions='flip') +``` + +## Step 4 + +Finally, we can overlay the catalog of data in the table onto a HiPS image using the [`show_coverage`](https://caltech-ipac.github.io/firefly_client/api/firefly_client.FireflyClient.html#firefly_client.FireflyClient.show_coverage) method. + +You will notice that there are colored squares that signify where the object was observed based on the RA and Dec given in the catalog. + +```{code-cell} ipython3 +r = fc.add_cell(2, 2, 2, 2, 'catalog-image', 'target') +if r['success']: + fc.show_coverage(); +``` + +Alternatively, we can queue a HiPS image using the method [`show_hips`](https://caltech-ipac.github.io/firefly_client/api/firefly_client.FireflyClient.html#firefly_client.FireflyClient.show_hips). However, this method requires target coordinates for the object you want to analyze. + +```{code-cell} ipython3 +target='229.851396;-9.720647;EQ_J2000' +viewer_id = 'hipsDiv' +hips_url = 'http://alasky.u-strasbg.fr/AllWISE/RGB-W4-W2-W1' + +r = fc.add_cell(2, 2, 2, 2, 'catalog-image', 'target') +if r['success']: + status = fc.show_hips(viewer_id=viewer_id, plot_id='aHipsID1-1', hips_root_url = hips_url, + Title='HiPS-WISE', WorldPt=target) +``` + +## Summary + +Firefly allows you to visualize data for specific targets. In conjuction with Astropy, one can manipulate a catalog of observations to display a light curve in an instantiated Firefly enviroment on their web browser. + +1. We import all necessary modules to create a Firefly client and to download the catalog of data for our target. + +2. We start the client in our web browser and prep the layout to appropiately display our tables, plots and images. + +3. We use the TAP schema to display the data for our target — [`558 Carmen`](https://irsa.ipac.caltech.edu/irsaviewer/?__action=table.search&request=%7B%22startIdx%22%3A0%2C%22SearchMethod%22%3A%22AllSky%22%2C%22RequestedDataSet%22%3A%22NEOWISE%20Reactivation%20Database%22%2C%22id%22%3A%22GatorQuery%22%2C%22tbl_id%22%3A%22tbl_id-cf48-45%22%2C%22META_INFO%22%3A%7B%22title%22%3A%22WISE-neowiser_p1ba_mch%20(AllSky)%22%2C%22tbl_id%22%3A%22tbl_id-cf48-45%22%2C%22tbl_pref_key%22%3A%22WISE-neowiser_p1ba_mch%22%7D%2C%22catalogProject%22%3A%22WISE%22%2C%22catalog%22%3A%22neowiser_p1ba_mch%22%2C%22constraints%22%3A%22objid%20like%20%27%25(558)%20Carmen%25%27%22%2C%22pageSize%22%3A100%7D&options=%7B%22backgroundable%22%3Atrue%2C%22pageSize%22%3A100%7D) — via a table and visualize such data through charts. + +4. We finally overlay the catalog onto a HiPS image to dynamically view where our target has been observed in space. + ++++ + +*** + +## About This Notebook + ++++ + +**Author:** Eric Bratton II (IRSA Scientist) in conjunction with the IRSA Science Team
+**Updated On:** 2024-07-31
+**Contact:** irsasupport@ipac.caltech.edu or https://irsa.ipac.caltech.edu/docs/help_desk.html diff --git a/tutorials/firefly/SEDs_in_Firefly.md b/tutorials/firefly/SEDs_in_Firefly.md new file mode 100644 index 00000000..eeb84f8b --- /dev/null +++ b/tutorials/firefly/SEDs_in_Firefly.md @@ -0,0 +1,723 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.2 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + +# Vetting SEDs in Firefly + ++++ + +*** + ++++ + +## Learning Goals + ++++ + +By the end of this tutorial, the following goals can be accomplished: +* Select a position and categories of data for search of possible nearby sources +* Pull photometry for different bands via TAP queries on chosen IRSA catalogs +* Add data columns from result to table, including energy density values (converted from magnitudes) +* Create a simple SED plot using compiled photometric data +* Display matching image cutouts from IRSA data sets for selected position + ++++ + +## Introduction + ++++ + +The purpose of this notebook is to show how to make and vet Spectral Energy Distributions (SEDs) using Firefly. All examples use the python package `pyvo` to search for catalogs and images from IRSA. + ++++ + +Detailed specifications for this notebook come from a paper led by Luisa Rebull on the selection of possible Young Stellar Objects (YSOs) in IC 417 (https://doi.org/10.3847/1538-3881/ace32f). + ++++ + +In this case, the SEDs generated by photometry data (from several different survey catalogs) near a given position can be compared with corresponding images to verify the location of a point source that could also be considered as a YSO if the graph shape is sound. + ++++ + +## Imports + ++++ + +Prior to starting Jupyterlab, you should specify the Firefly server by setting the `FIREFLY_URL` environment variable (use the value https://irsa.ipac.caltech.edu/irsaviewer if you're not sure), or by one of the other ways listed on the [jupyter_firefly_extension page](https://github.com/Caltech-IPAC/jupyter_firefly_extensions). + ++++ + +The packages needed for this notebook are in the `requirements.txt` file. They can be installed with `pip install -r requirements.txt` before you start your Jupyterlab session. + ++++ + +* _astropy.units_ - for specifying and manipulating units +* _astropy.constants_ - for constants +* _astropy.coordinates.Skycoord_ - for representing coordinates +* _astropy.table.QTable_ - for tables with units +* _firefly_client.FireflyClient_ - Python API to Firefly for displaying tables, images and charts +* _numpy_ - for working with arrays +* _pyvo_ - for queries to Virtual Observatory services at the archives +* _jupytext_ - for working with Markdown notebooks. It must be installed before your Jupyterlab session is started. See [these instructions](https://github.com/NASA-NAVO/navo-workshop/blob/main/00_SETUP.md#8-handling-notebooks-in-myst-markdown-format) for helpful information. + ++++ + +To run the notebook by itself, run the cell below (skip if you already have the requirements installed): + +```{code-cell} ipython3 +# Install libraries if necessary by uncommenting the following +# !pip install -r requirements.txt +``` + +Call the imports below: + +```{code-cell} ipython3 +import astropy.units as u +from astropy import constants as const +from astropy.coordinates import SkyCoord +from astropy.table import QTable +from astropy.utils.data import download_file +from firefly_client import FireflyClient +import numpy as np +import pyvo +``` + +## Choose Target as Example + ++++ + +From [Figure 10](https://iopscience.iop.org/article/10.3847/1538-3881/ace32f#ajace32ff10) of the referenced paper, pick the source in the upper right corner (J052736.37+344940.6): + +```{code-cell} ipython3 +target = SkyCoord(ra="05h27m36.37s", dec="+34d49m40.6s") +``` + +## Get Photometry from IRSA + ++++ + +The available data at IRSA include the following catalogs (with matching radius at 1 arcsec except where noted by reference paper): +* Gaia DR3 +* 2MASS +* Spitzer-IRAC (GLIMPSE? SEIP Source List?) +* Spitzer-MIPS-24 (GLIMPSE? SEIP Source List?) +* AllWISE +* CatWISE +* unWISE +* MSX +* Akari +* Herschel-PACS (70um and 160um) + +The [NITARP Wiki page](https://vmcoolwiki.ipac.caltech.edu/index.php/Central_wavelengths_and_zero_points) on central wavelengths may be helpful for finding zero-point information for specific catalogs, as well as the more general [astroquery service](https://astroquery.readthedocs.io/en/latest/svo_fps/svo_fps.html) on SVO filter data. + ++++ + +Whlie this notebook will focus on a subset of the above list (2MASS, Gaia DR3, and WISE data), note that there is a section where additional data can be included as well. + ++++ + +The variable `phot_tbl` is the table containing the photometry for the target and all the derived quantities needed to make SED plots: +* Right ascension (in degrees) +* Declination (in degrees) +* Wavelength for the bandpass (in microns) +* Photometry measurement +* Photometry uncertainty +* Is the measurement an upper limit? (Note: 1 means yes, 0 means no) +* Zeropoint for the bandpass in units of Janskys (needed for converting photometric measurements to energy densities) + ++++ + +Set the variables for the photmetry table and each quantity in that data structure: + +```{code-cell} ipython3 +phot_tbl = QTable(names=['ra', 'dec', 'wavelength', 'mag', 'magerr', 'upper_limit', 'zeropoint'], + units=[u.deg, u.deg, u.micron, None, None, None, u.Jy]) +``` + +We query catalog data using IRSA's TAP (VO Table Access Protocol) service. It's sufficient to set up the service once, at the beginning of the session: + +```{code-cell} ipython3 +irsa_tap = pyvo.dal.TAPService("https://irsa.ipac.caltech.edu/TAP") +``` + +### Retrieve 2MASS photometry + ++++ + +To start, define a function to retrieve 2MASS photometry via a TAP query to IRSA that includes upper limits (note that only the `ph_qual` column on photometric quality of source is used and not the `rd_flg` column on "read flag"): + +```{code-cell} ipython3 +def get_2mass_phot(target, radius=1*u.arcsec): + """Get photometry from 2MASS + + Parameters: + ----------- + target: astropy.coordinates.SkyCoord + coordinates of the target(s) + + radius: astropy.units.Quantity + matching radius, default 1*u.arcsec + + Returns: + -------- + rows: list + lists of photometry points to add to table + """ + + query = f""" + SELECT ra,dec,j_m,j_msigcom,h_m,h_msigcom,k_m,k_msigcom,ph_qual,rd_flg + FROM fp_psc + WHERE CONTAINS(POINT('ICRS', ra, dec), + CIRCLE('ICRS', {target.ra.deg}, {target.dec.deg}, + {radius.to('deg').value}))=1 + """ + + results = irsa_tap.search(query) + + rowj = [results["ra"]*u.deg, + results["dec"]*u.deg, + 1.235*u.micron, + results["j_m"][0], + results["j_msigcom"][0], + 1 if results["ph_qual"] == "U" else 0, + 1594*u.Jy] + + rowh = [results["ra"]*u.deg, + results["dec"]*u.deg, + 1.662*u.micron, + results["h_m"][0], + results["h_msigcom"][0], + 1 if results["ph_qual"] == "U" else 0, + 1024*u.Jy] + + rowks = [results["ra"]*u.deg, + results["dec"]*u.deg, + 2.159*u.micron, + results["k_m"][0], + results["k_msigcom"][0], + 1 if results["ph_qual"] == "U" else 0, + 666.7*u.Jy] + + return([rowj, rowh, rowks]) +``` + +Consider that while the search radius is currently set at 1 degree from the position, that value can be adjusted by changing what the number on the `radius` line is. + +Now gather the rows of 2MASS data and add each of them to the photometry table: + +```{code-cell} ipython3 +rows = get_2mass_phot(target) +``` + +```{code-cell} ipython3 +for row in rows: + phot_tbl.add_row(row) +``` + +### Retrieve AllWISE Photometry + ++++ + +According to the paper referenced above, the detections from the AllWISE catalog were retained if the data quality flags were A, B, or C; if the data quality flag was Z, then the data were provisionally retained with a very large error bar, 30% larger than what appears in the catalog. + ++++ + +Based on that information, define a function to release AllWISE photometry via a TAP query to IRSA that includes the needed data quality flags and retains upper limits: + +```{code-cell} ipython3 +def get_allwise_phot(target, radius=1*u.arcsec): + """Get photometry from AllWISE + + Parameters: + ----------- + target: astropy.coordinates.SkyCoord + coordinates of the target(s) + + radius: astropy.units.Quantity + matching radius, defaults to 1*u.arcsec + + Returns: + -------- + rows: list + lists of photometry points to add to table + """ + + query = f""" + SELECT ra,dec,w1mpro,w1sigmpro,w2mpro,w2sigmpro,w3mpro, + w3sigmpro,w4mpro,w4sigmpro,ph_qual + FROM allwise_p3as_psd + WHERE CONTAINS(POINT('ICRS', ra, dec), + CIRCLE('ICRS', {target.ra.deg}, {target.dec.deg}, + {radius.to('deg').value}))=1 + """ + + results = irsa_tap.search(query) + + roww1 = [results["ra"]*u.deg, + results["dec"]*u.deg, + 3.4*u.micron, + results["w1mpro"][0], + results["w1sigmpro"][0], + 1 if results["ph_qual"] == "U" else 0, + 309.54*u.Jy] + + roww2 = [results["ra"]*u.deg, + results["dec"]*u.deg, + 4.6*u.micron, + results["w2mpro"][0], + results["w2sigmpro"][0], + 1 if results["ph_qual"] == "U" else 0, + 171.79*u.Jy] + + roww3 = [results["ra"]*u.deg, + results["dec"]*u.deg, + 12*u.micron, + results["w3mpro"][0], + results["w3sigmpro"][0], + 1 if results["ph_qual"] == "U" else 0, + 31.676*u.Jy] + + roww4 = [results["ra"]*u.deg, + results["dec"]*u.deg, + 22*u.micron, + results["w4mpro"][0], + results["w4sigmpro"][0], + 1 if results["ph_qual"] == "U" else 0, + 8.3635*u.Jy] + + return([roww1, roww2, roww3, roww4]) +``` + +```{code-cell} ipython3 +rows = get_allwise_phot(target) +``` + +```{code-cell} ipython3 +for row in rows: + phot_tbl.add_row(row) +``` + +### Retrieve Gaia DR3 Photometry + ++++ + +Define a function to retrieve Gaia DR3 photometry via a TAP query to IRSA (not considering upper limits as Gaia DR3 ony provides "detections or not" info so actual limits are not given): + +```{code-cell} ipython3 +def get_gaia_phot(target, radius=1*u.arcsec): + """Get photometry from Gaia DR3 + + Parameters: + ----------- + target: astropy.coordinates.SkyCoord + coordinates of the target(s) + + radius: astropy.units.Quantity + matching radius, default is 1*u.arcsec + + Returns: + -------- + rows: list + lists of photometry points to add to table + """ + + query = f""" + SELECT designation,ra,ra_error,dec,dec_error,ra_dec_corr,phot_g_mean_flux_over_error,phot_g_mean_mag, + phot_bp_mean_flux_over_error,phot_bp_mean_mag,phot_rp_mean_flux_over_error,phot_rp_mean_mag + FROM gaia_dr3_source + WHERE CONTAINS(POINT('ICRS', ra, dec), + CIRCLE('ICRS', {target.ra.deg}, {target.dec.deg}, + {radius.to('deg').value}))=1 + """ + + results = irsa_tap.search(query) + + rowg = [results["ra"]*u.deg, + results["dec"]*u.deg, + 0.622*u.micron, + results["phot_g_mean_mag"][0], + 2.5/(np.log(10)*results["phot_g_mean_flux_over_error"][0]), + 0, + 3228.75*u.Jy] + + rowbp = [results["ra"]*u.deg, + results["dec"]*u.deg, + 0.511*u.micron, + results["phot_bp_mean_mag"][0], + 2.5/(np.log(10)*results["phot_bp_mean_flux_over_error"][0]), + 0, + 3552.01*u.Jy] + + rowrp = [results["ra"]*u.deg, + results["dec"]*u.deg, + 0.7769*u.micron, + results["phot_rp_mean_mag"][0], + 2.5/(np.log(10)*results["phot_rp_mean_flux_over_error"][0]), + 0, + 2554.95*u.Jy] + + return([rowg, rowbp, rowrp]) +``` + +```{code-cell} ipython3 +rows = get_gaia_phot(target) +``` + +```{code-cell} ipython3 +for row in rows: + phot_tbl.add_row(row) +``` + +### Retrieve CatWISE Photometry + ++++ + +Define a function to retrieve CatWISE photometry via a TAP query to IRSA that includes upper limits (note that CatWISE2020 Catalog is being used rather than CatWISE Preliminary Catalog): + +```{code-cell} ipython3 +def get_catwise_phot(target, radius=1*u.arcsec): + """Get photometry from CatWISE + + Parameters: + ----------- + target: astropy.coordinates.SkyCoord + coordinates of the target(s) + + radius: astropy.units.Quantity + matching radius, defaults to 1*u.arcsec + + Returns: + -------- + rows: list + lists of photometry points to add to table + """ + + query = f""" + SELECT ra,dec,w1mpro,w1sigmpro,w2mpro,w2sigmpro + FROM catwise_2020 + WHERE CONTAINS(POINT('ICRS', ra, dec), + CIRCLE('ICRS', {target.ra.deg}, {target.dec.deg}, + {radius.to('deg').value}))=1 + """ + + results = irsa_tap.search(query) + + roww1 = [results["ra"]*u.deg, + results["dec"]*u.deg, + 3.4*u.micron, + results["w1mpro"][0], + results["w1sigmpro"][0], + 1 if results["w1sigmpro"] is None else 0, + 309.54*u.Jy] + + roww2 = [results["ra"]*u.deg, + results["dec"]*u.deg, + 4.6*u.micron, + results["w2mpro"][0], + results["w2sigmpro"][0], + 1 if results["w2sigmpro"] is None else 0, + 171.79*u.Jy] + + return([roww1, roww2]) +``` + +```{code-cell} ipython3 +rows = get_catwise_phot(target) +``` + +```{code-cell} ipython3 +for row in rows: + phot_tbl.add_row(row) +``` + +### Retrieve unWISE Photometry + ++++ + +Define a function to retrieve unWISE photometry via a TAP query to IRSA(note that flux units are given in nano-mag, zero-point is carried over from AllWISE, and no flag for upper limits is given): + +```{code-cell} ipython3 +def get_unwise_phot(target, radius=1*u.arcsec): + """Get photometry from CatWISE + + Parameters: + ----------- + target: astropy.coordinates.SkyCoord + coordinates of the target(s) + + radius: astropy.units.Quantity + matching radius, defaults to 1*u.arcsec + + Returns: + -------- + rows: list + lists of photometry points to add to table + """ + + query = f""" + SELECT ra,dec,flux_1,dflux_1,flux_2,dflux_2,fluxlbs_1 + FROM unwise_2019 + WHERE CONTAINS(POINT('ICRS', ra, dec), + CIRCLE('ICRS', {target.ra.deg}, {target.dec.deg}, + {radius.to('deg').value}))=1 + """ + + results = irsa_tap.search(query) + + roww1 = [results["ra"]*u.deg, + results["dec"]*u.deg, + 3.4*u.micron, + pow(10,9)*results["flux_1"][0], + pow(10,9)*results["dflux_1"][0], + 0, + 309.54*u.Jy] + + roww2 = [results["ra"]*u.deg, + results["dec"]*u.deg, + 4.6*u.micron, + pow(10,9)*results["flux_2"][0], + pow(10,9)*results["dflux_2"][0], + 0, + 171.79*u.Jy] + + return([roww1, roww2]) +``` + +```{code-cell} ipython3 +rows = get_unwise_phot(target) +``` + +```{code-cell} ipython3 +for row in rows: + phot_tbl.add_row(row) +``` + +### Retrieve Optional Photometry + ++++ + +Insert more data retrievals here, following the above formats. + +Note: After more columns are added in the conversion to spectral energy density, the `phot_tbl.add_row` functions will thrown an exception that number of values doesn't match the number of columns. + +```{code-cell} ipython3 +# SEIP +# GLIMPSE + +# MSX, AKARI, Herschel PACS + +# Pan-STARRS, UKIDSS? +``` + +## Convert Magnitudes to Energy Densities + ++++ + +Use the zeropoint information embedded by the catalog retrieval functions to compute energy densities: + +```{code-cell} ipython3 +factor = (const.c*phot_tbl["wavelength"]**-1).to(u.Hz) +``` + +```{code-cell} ipython3 +phot_tbl["lam_flam"] = ((factor*phot_tbl["zeropoint"] * + 10**(-0.4*phot_tbl["mag"])) + ).to(u.erg*u.s**-1*u.cm**-2) +``` + +As the above formula was for the photometry measurements given, compute the photometry uncertainty using a similar formula: + +```{code-cell} ipython3 +phot_tbl["lam_flam_err"] = phot_tbl["lam_flam"]*phot_tbl["magerr"]*np.log(10)/2.5 +``` + +Check the energy density values for each converted value below: + +```{code-cell} ipython3 +phot_tbl["lam_flam"] +``` + +```{code-cell} ipython3 +phot_tbl["lam_flam_err"] +``` + +Run the following cell to view the full photometry table and its values for each column (ex. zeropoint, upper limit): + +```{code-cell} ipython3 +phot_tbl +``` + +## Upload to Firefly + ++++ + +This notebook assumes that [jupyter_firefly_extensions](https://github.com/Caltech-IPAC/jupyter_firefly_extensions) has been installed, and that the Firefly server to use has been specified before Jupyterlab was started. + +If everything has been properly configured, executing the next cell will bring up a Firefly tab in Jupyterlab with the message "Firefly Ready": + +```{code-cell} ipython3 +# Uncomment to use the jupyter_firefly_extensions +#fc = FireflyClient.make_lab_client() + +# Uncomment to use a separate web browser tab +fc = FireflyClient.make_client(url="https://irsa.ipac.caltech.edu/irsaviewer") +``` + +In the event that there are problems with the tab opened above, run the below command to obtain a web link that can be opened in a browser directly: + +```{code-cell} ipython3 +# Temporary work-around to Firefly error for Slate and/or Internet connection problems +fc.display_url() +``` + +Write the photometry table to a FITS file: + +```{code-cell} ipython3 +tblpath = "./phot_tbl.fits" +phot_tbl.write(tblpath, format="fits", overwrite=True) +``` + +Upload the table to Firefly: + +```{code-cell} ipython3 +tval = fc.upload_file(tblpath) +``` + +Show the table in Firefly: + +```{code-cell} ipython3 +fc.show_table(tval, tbl_id="photometry", title="SED Photometry") +``` + +Specify the columns and markers for the SED plot: + +```{code-cell} ipython3 +trace1 = dict(tbl_id="photometry", x="tables::wavelength", y="tables::lam_flam", mode="markers", + type="scatter", error_y=dict(array="tables::lam_flam_err"), + marker=dict(size=4)) +trace_data = [trace1] +``` + +Specify the title and axes for the SED plot: + +```{code-cell} ipython3 +layout_s = dict(title="SED", xaxis=dict(title="Wavelength (microns)", type="log"), + yaxis=dict(title="Energy density (erg/s/cm2)", type="log")) +``` + +Display the SED plot in Firefly: + +```{code-cell} ipython3 +fc.show_chart(layout=layout_s, data=trace_data) +``` + +## Retrieve and Display Images + ++++ + +Use queries directed at Simple Image Access services to retrieve images: + +```{code-cell} ipython3 +irsa_sia = pyvo.dal.SIAService("https://irsa.ipac.caltech.edu/cgi-bin/2MASS/IM/nph-im_sia?type=at&ds=asky&") +``` + +### Get 2MASS Images + +```{code-cell} ipython3 +def get_2mass_images(target, search_size=1*u.arcsec): + """Retrieve 2MASS images + + Parameters: + ----------- + target: astropy.coordinates.SkyCoord + coordinates of the target(s) + + search_size: astropy.units.Quantity + matching radius, defaults to 1*u.arcsec + + Returns: + -------- + j_filename: `str` + path to J-band image in FITS format + + h_filename: `str` + path to H-band image in FITS format + + k_filename: `str` + path to K-band image in FITS format + """ + im_table = irsa_sia.search(pos=target, size=search_size) + url_j = url_h = url_k = None + # Get URL for the first instance of each band + for i in range(len(im_table)): + if url_j is None and im_table[i]["band"] == "J": + url_j = im_table[i].getdataurl() + if url_h is None and im_table[i]["band"] == "H": + url_h = im_table[i].getdataurl() + if url_k is None and im_table[i]["band"] == "K": + url_k = im_table[i].getdataurl() + j_filename = download_file(url_j, cache=True) + h_filename = download_file(url_h, cache=True) + k_filename = download_file(url_k, cache=True) + return (j_filename, h_filename, k_filename) +``` + +```{code-cell} ipython3 +j_fname, h_fname, k_fname = get_2mass_images(target) +``` + +```{code-cell} ipython3 +fc.show_fits(fc.upload_file(j_fname), plot_id="2MASS J") +fc.show_fits(fc.upload_file(h_fname), plot_id="2MASS H") +fc.show_fits(fc.upload_file(k_fname), plot_id="2MASS K") +``` + +```{code-cell} ipython3 +fc.set_zoom(plot_id="2MASS J", factor=4.0) +fc.set_pan(plot_id="2MASS J", x=target.ra.deg, + y=target.dec.deg, coord="j2000") +fc.set_zoom(plot_id="2MASS H", factor=4.0) +fc.set_pan(plot_id="2MASS H", x=target.ra.deg, + y=target.dec.deg, coord="j2000") +fc.set_zoom(plot_id="2MASS K", factor=4.0) +fc.set_pan(plot_id="2MASS K", x=target.ra.deg, + y=target.dec.deg, coord="j2000") +``` + +In the future, the user should be able to implement turning on "Align and Lock by WCS" using the Python API as part of this notebook. + ++++ + +The current alternative is to use the following link to launch IRSA Finder Chart in a separate browser and turn on that function there: +https://irsa.ipac.caltech.edu/applications/finderchart/servlet/api?mode=getResult&locstr=270.599026+-24.147018+Equ+J2000&subsize=0.0167&sources=2MASS&DoSearch=true + +In that Firefly display, it should be possible to turn on "Align and Lock by WCS" in the image toolbar. + ++++ + +*** + ++++ + +## About This Notebook + ++++ + +**Author:** David Shupe (IRSA Scientist) and Joyce Kim (IRSA Scientist) in conjunction with the IRSA Science Team + +**Updated On:** 2024-07-31 + +**Contact:** irsasupport@ipac.caltech.edu or https://irsa.ipac.caltech.edu/docs/help_desk.html + +```{code-cell} ipython3 + +``` diff --git a/tutorials/requirements.txt b/tutorials/requirements.txt index 14218b6d..b6e83e8f 100644 --- a/tutorials/requirements.txt +++ b/tutorials/requirements.txt @@ -10,5 +10,9 @@ pandas>=1.5.2 dask[distributed] psutil s3fs +firefly-client +jupyter-firefly-extensions # For supporting myst-based notebooks jupytext +# For firefly-client packaging bug +setuptools