{ "cells": [ { "cell_type": "markdown", "id": "8c8138ef-e687-444e-95b1-9797654f3f62", "metadata": {}, "source": [ "# Modifying the Default Values for Surface Error and Aperture Efficiency\n", "\n", "This notebook shows how you can modify the defaults for surface error and aperture efficiency.\n", "We encourage users of the GBT to rely on the Observatory-measured values and functions for surface error and aperture efficiency, which are implemented in dysh. However, advanced users may wish to modify the values or functions; this example shows how to do that.\n" ] }, { "cell_type": "markdown", "id": "61f26081-b9ab-4a4c-bb51-38358ac33a8f", "metadata": {}, "source": [ "## Refresher on Aperture Efficiency and Brightness Scales\n", "The aperture efficiency $\\eta_a$ is determined by:\n", "\n", "$$\\eta_a = \\eta_0~G(ZD) \\exp(-(4\\pi\\epsilon/\\lambda)^2),$$\n", "\n", "where $\\eta_0$ is the long wavelength aperture efficiency, $G(ZD)$ is the gain correction factor\n", "at a zenith distance $ZD$, $\\epsilon$ is the surface error, and $\\lambda$ is the wavelength.\n", "\n", "To scale antenna temperature $T_a$ to brightness tempeature $T_a^*$:\n", "\n", "$$ T_a^* = T_a~\\exp(\\tau~A)/(\\eta_a~\\eta_l),$$\n", "\n", "where $\\tau$ is the zenith opacity, $A$ is the airmass, and $\\eta_l$ is the loss efficiency. To scale to flux $S_\\nu$\n", "\n", "$$ S_\\nu = 2~k~T_a^*/A_p, $$\n", "\n", "where $k$ is Boltzmann's constant is $A_p$ is the physical aperture of the telescope. \n", "\n", "\n" ] }, { "cell_type": "markdown", "id": "0cb232c9-e7a2-4344-a3fe-492f939630eb", "metadata": {}, "source": [ "## What dysh Does\n", "\n", "When you calibrate and scale data through, e.g. \n", "[GBTFITSLoad.getps](https://dysh.readthedocs.io/en/latest/reference/modules/dysh.fits.html#dysh.fits.GBTFITSLoad.getps),\n", "dysh uses the `GBTGainCorrection` class to manage the calculations described above. `GBTGainCorrection` maintains $G(ZD)$ and surface error as a function of date as derived in \n", "[GBT Memo 301](https://library.nrao.edu/public/memos/gbt/GBT_301.pdf). \n", "You can provide your own values for $\\eta_a$ or $\\epsilon$ in the standard calibration routines (you must provide $\\tau$)." ] }, { "cell_type": "markdown", "id": "03ae6cc9-3398-448c-843c-3045f36c0dca", "metadata": {}, "source": [ "## Dysh commands\n", "\n", "The following dysh commands are introduced (leaving out all the function arguments):\n", "\n", " filename = dysh_data()\n", " sdf = GBTFITSLoad()\n", " sb = sdf.getps()\n", " ta = sb.timeaverage()\n" ] }, { "cell_type": "markdown", "id": "814b589f-dab5-4b3b-9866-a5448cdbcf14", "metadata": {}, "source": [ "\n", "## Loading Modules\n", "We start by loading the modules we will use for the data reduction. \n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "b4967550-2ca1-4931-b53b-6f9868718490", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "import" ] }, "outputs": [], "source": [ "# These modules are required for the data reduction.\n", "from dysh.fits.gbtfitsload import GBTFITSLoad\n", "from astropy import units as u\n", "import numpy as np\n", "from dysh.log import init_logging\n", "\n", "# These modules are used for file I/O\n", "from dysh.util.files import dysh_data\n", "from pathlib import Path" ] }, { "cell_type": "markdown", "id": "d723b880-988b-45b9-9772-01eba8f02571", "metadata": {}, "source": [ "## Setup\n", "\n", "dysh uses a logger to communicate. If you are working in the command\n", "line, then the logging is setup for you. If you are working in a\n", "jupyter lab instance, then you need to set it up. You can do so using\n", "the init_logging function imported above. As an argument, init_logging\n", "takes a number, the verbosity level. level 0 is for error messages\n", "only, 1 for warning, 2 for info and 3 for debug. Here we set it to\n", "level 2." ] }, { "cell_type": "code", "execution_count": 2, "id": "a62c987f-ccb5-4a94-b66b-52fa9b370e2e", "metadata": {}, "outputs": [], "source": [ "init_logging(2)\n", "\n", "# also create a local \"output\" directory where temporary notebook files can be stored.\n", "output_dir = Path.cwd() / \"output\"\n", "output_dir.mkdir(exist_ok=True)" ] }, { "cell_type": "markdown", "id": "87669763-8d96-4521-9e81-f69d7213e133", "metadata": {}, "source": [ "## Data Retrieval\n", "\n", "Download the example SDFITS data, if necessary." ] }, { "cell_type": "code", "execution_count": 3, "id": "6bc88bc5-986d-4eae-b1c7-6398cc9ddd5a", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "wget" ] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "13:59:12.102 I Resolving test=getps -> AGBT05B_047_01/AGBT05B_047_01.raw.acs/\n" ] } ], "source": [ "filename = dysh_data(test=\"getps\")" ] }, { "cell_type": "markdown", "id": "e0bf5028-e5b2-43c3-9a0c-6416dc02e2ec", "metadata": {}, "source": [ "## Data Loading\n", "\n", "Next, we use `GBTFITSLoad` to load the data, and then its `summary` method to inspect its contents." ] }, { "cell_type": "code", "execution_count": 4, "id": "93a62e3a-c95d-475b-8602-b5b8b7934733", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "load" ] }, "outputs": [], "source": [ "sdfits = GBTFITSLoad(filename)" ] }, { "cell_type": "code", "execution_count": 5, "id": "90d482e1-3953-49da-9be6-49605ae9cf64", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SCANOBJECTVELOCITYPROCPROCSEQNRESTFREQDOPFREQ# IF# POL# INT# FEEDAZIMUTHELEVATION
51NGC52914386.0OnOff11.4204051.42040512111198.343118.6427
52NGC52914386.0OnOff21.4204051.42040512111198.930618.7872
53NGC52914386.0OnOff11.4204051.42040512111199.330518.3561
54NGC52914386.0OnOff21.4204051.42040512111199.915718.4927
55NGC52914386.0OnOff11.4204051.42040512111200.304218.0575
56NGC52914386.0OnOff21.4204051.42040512111200.890618.1860
57NGC52914386.0OnOff11.4204051.42040512111202.327517.3853
58NGC52914386.0OnOff21.4204051.42040512111202.919217.4949
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sdfits.summary()" ] }, { "cell_type": "markdown", "id": "e84c5009-96f4-489d-bc9d-89de390d53c9", "metadata": {}, "source": [ "## Data Reduction\n", "We calibrate a few scans of the position switched observations, giving a value for `zenith_opacity` but leaving `dysh` to calculate the aperture efficiency.\n", "We will calibrate scans 51, 53 and 55.\n", "We use a zenith opacity of 0.08, but the exact value is not important here.\n", "And, we request that the data be calibrated to units of flux, so that the aperture efficiency goes into the calculations." ] }, { "cell_type": "code", "execution_count": 6, "id": "fe403fdf-fb62-4cf9-afb2-4d5a96c4f98b", "metadata": {}, "outputs": [], "source": [ "scans = [51,53,55]" ] }, { "cell_type": "code", "execution_count": 7, "id": "684126da-97d4-4afb-8625-43160340cab1", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "getps", "test" ] }, "outputs": [], "source": [ "ps_scan_block = sdfits.getps(scan=scans, ifnum=0, plnum=0, fdnum=0, units=\"flux\", \n", " zenith_opacity=0.08)" ] }, { "cell_type": "markdown", "id": "4bc2b25f-dc55-4a4b-8f8d-068b6951cb52", "metadata": {}, "source": [ "### Providing Aperture Efficiency or Surface Error\n", "\n", "Now, we calibrate the same data, but we provide a value for the aperture efficiency.\n", "We use a value of $25\\%$ (``ap_eff=0.25``)." ] }, { "cell_type": "code", "execution_count": 8, "id": "8a12633b-ed26-44ec-bf55-2ad4ee59e546", "metadata": {}, "outputs": [], "source": [ "ps_scan_block_ap_eff = sdfits.getps(scan=scans, ifnum=0, plnum=0, fdnum=0, units=\"flux\", \n", " zenith_opacity=0.08, ap_eff=0.25)" ] }, { "cell_type": "markdown", "id": "a2ecb3d6-e3b5-4c40-aa35-294ca3b00e11", "metadata": {}, "source": [ "Alternatively, one could specify the surface error using the ``surface_error`` argument.\n", "The value of the ``surface_error`` must be a quantity with units compatible with a length.\n", "(You can't give both surface error and aperture efficiency because the latter is computed from the former.)" ] }, { "cell_type": "code", "execution_count": 9, "id": "aa9bdccc-fef5-4258-96bf-0ee6d4e9f146", "metadata": {}, "outputs": [], "source": [ "ps_scan_block_surf_err = sdfits.getps(scan=scans, ifnum=0, plnum=0, fdnum=0, units=\"flux\", \n", " zenith_opacity=0.08, surface_error=400*u.micron)" ] }, { "cell_type": "markdown", "id": "31e83a31-953c-4f89-8f39-77d5a8f31e95", "metadata": {}, "source": [ "Now we print the different $\\eta_a$ for the first scan in each ``ScanBlock``.\n", "You can see that at this wavelength, the surface error does not have much of an effect because $\\epsilon << \\lambda$. (400 $\\mu$m vs. 21 cm)" ] }, { "cell_type": "code", "execution_count": 10, "id": "df8aff3b-6865-4635-ad12-71782a57a9a1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.7047,0.2500,0.7045\n" ] } ], "source": [ "print(f\"{np.mean(ps_scan_block[0].ap_eff):.4f},{np.mean(ps_scan_block_ap_eff[0].ap_eff):.4f},{np.mean(ps_scan_block_surf_err[0].ap_eff):.4f}\")" ] }, { "cell_type": "markdown", "id": "18cfb0fb-43fb-4fe9-add7-05315122af4b", "metadata": {}, "source": [ "But the aperture efficiency does make a difference in the derived flux." ] }, { "cell_type": "code", "execution_count": 11, "id": "995dd61b-ffcd-4cc9-842d-325d871ece8c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "S_nu = 0.18 Jy\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "27565caeefeb455ebf06e65e2779db7b", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(HBox(children=(Button(description='Clear All Regions', style=ButtonStyle(), tooltip='Clear all …" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "a = ps_scan_block.timeaverage()\n", "print(f\"S_nu = {a.stats()['median']:.3}\")\n", "a.plot();" ] }, { "cell_type": "code", "execution_count": 12, "id": "7042ffbd-b36d-4c4c-9e4e-f41cfa8a7114", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "S_nu = 0.508 Jy\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "5e59227d6f2b4ed7bd4e875d1ac6cad2", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(HBox(children=(Button(description='Clear All Regions', style=ButtonStyle(), tooltip='Clear all …" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "b = ps_scan_block_ap_eff.timeaverage()\n", "print(f\"S_nu = {b.stats()['median']:.3}\")\n", "b.plot();" ] }, { "cell_type": "markdown", "id": "ec8eead9-4419-4690-9486-c90558536029", "metadata": {}, "source": [ "The weighted average aperture efficiency, surface error, and zenith opacity are stored in the ``Spectrum`` metadata." ] }, { "cell_type": "code", "execution_count": 13, "id": "ebdf7281-4c1f-4408-b936-5552a221147f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "eta = 0.705, epsilon = 230.0 micron, tau = 0.08\n" ] } ], "source": [ "print(f\"eta = {a.meta['AP_EFF']:.3f}, epsilon = {a.meta['SURF_ERR']:.1f} {a.meta['SE_UNIT']}, tau = {a.meta['TAU_Z']:.2f}\")" ] }, { "cell_type": "markdown", "id": "7f63d58a-d86b-4d16-a41a-6154a958141b", "metadata": {}, "source": [ "## What if I want to change $G(ZD)$ or the surface error model?\n", "This is advanced usage and requires you to fork or clone ``dysh``, then modify ``src/dysh/data/gaincorrection.tab``. If you have questions, consult with a dysh developer. " ] }, { "cell_type": "markdown", "id": "80e50fb4-c350-464a-bd37-2e93e966ea98", "metadata": {}, "source": [ "## Final Stats\n", "\n", "Finally, at the end we compute some statistics over a spectrum, merely as a checksum if the notebook is reproducible." ] }, { "cell_type": "code", "execution_count": 14, "id": "665a3b0e-7bcb-4387-b7cd-2faa172d4b30", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "13:59:14.215 I rms is OK \n" ] } ], "source": [ "b.check_stats(0.11950689 * u.Jy)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.9" }, "toc": { "base_numbering": 0 } }, "nbformat": 4, "nbformat_minor": 5 }