{ "cells": [ { "cell_type": "markdown", "id": "88e808b0-5df1-4836-b02f-8d28585f4904", "metadata": {}, "source": [ "# SubBeamNod Data Reduction\n", "\n", "This notebook shows how to use dysh to calibrate an SubBeamNod observation via two different methods. It retrieves and calibrates SubBeamNod scans using `GBTFITSLoad.subbeamnod()` which returns a `ScanBlock` object. \n", "\n", "## 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", " sdf.select()\n", " sb = sdf.subbeamnod()\n", " ta = sb.timeaverage()\n", " ta.baseline()\n", " ta.average()\n", " ta.plot()\n", "\n", "## Loading Modules\n", "We start by loading the modules we will use for the data reduction. \n" ] }, { "cell_type": "code", "execution_count": 1, "id": "71a0f9ba-9f38-408d-ba57-2630c1525a64", "metadata": {}, "outputs": [], "source": [ "# These modules are required for working with the data.\n", "from dysh.log import init_logging\n", "from dysh.fits.gbtfitsload import GBTFITSLoad\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": "ae0b0478-ca2a-4de4-bebd-692dff0105d2", "metadata": {}, "source": [ "## Setup \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.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "70cec341-9e79-48d9-afba-a0f84bd52e00", "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": "efc7bb5b-7979-4863-a4a2-7270760c2ee9", "metadata": {}, "source": [ "## Data Retrieval\n", "\n", "Download the example SDFITS data, if necessary." ] }, { "cell_type": "code", "execution_count": 3, "id": "f07cfb32-6864-4ac4-94f8-4c2b66b981c4", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "20:09:18.591 I Resolving example=subbeamnod -> subbeamnod/data/AGBT13A_124_06/AGBT13A_124_06.raw.acs/AGBT13A_124_06.raw.acs.fits\n" ] } ], "source": [ "filename = dysh_data(example=\"subbeamnod\")" ] }, { "cell_type": "markdown", "id": "cf925ad1-e149-46dd-9728-53ea2142fbf8", "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": "1b12df99-20b2-4f8b-95c3-802be4ffaf3c", "metadata": {}, "outputs": [], "source": [ "sdfits = GBTFITSLoad(filename)" ] }, { "cell_type": "markdown", "id": "337f7f2e-038d-4479-ba29-a66f46440b30", "metadata": {}, "source": [ "The returned `sdfits` can be probed for information.\n", "You can also print a concise (or verbose if you choose verbose=True) summary of the data." ] }, { "cell_type": "code", "execution_count": 5, "id": "259fec35-f69a-4061-ad37-c2235102af4c", "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", "
SCANOBJECTVELOCITYPROCPROCSEQNRESTFREQDOPFREQ# IF# POL# INT# FEEDAZIMUTHELEVATION
44vIIzw3116090.0SubBeamNod148.94095548.990955221002353.896747.7582
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sdfits.summary()" ] }, { "cell_type": "markdown", "id": "570e7d59-10ba-4826-9b98-bec3515cf783", "metadata": {}, "source": [ "There is only one scan, using SubBeamNod. The scan is 44.\n" ] }, { "cell_type": "markdown", "id": "da3849c2-0c34-43e1-9a36-6874fea74d91", "metadata": {}, "source": [ "## Data Reduction\n", "\n", "### Single Scan\n", "\n", "To retrieve and calibrate a SubBeamNod scan we use `sdfits.subbeamnod`. This method returns a `ScanBlock`, with one element per scan and per intermediate frequency. \n", "\n", "#### Calibration per Cycle\n", "\n", "There are two different methods for calibrating a SubBeamNod scan. The first, with `method=\"cycle\"` (the default) averages the data in each subreflector state for each cycle of integrations. That is, it separates the data into one signal/reference pair for each pair of subreflector states (on source and off source). Then calibrates each signal/reference pair independently and finally time averages the calibrated spectra." ] }, { "cell_type": "code", "execution_count": 6, "id": "d86e90f0-a285-4ce3-99bf-5aa48f524eeb", "metadata": {}, "outputs": [], "source": [ "sbn_scan_block = sdfits.subbeamnod(scan=44, fdnum=1, ifnum=0, plnum=0, method='cycle')" ] }, { "cell_type": "markdown", "id": "3d3b9fea-ac07-4415-bee2-41dd2e544e77", "metadata": {}, "source": [ "#### Time Averaging\n", "\n", "To time average the contents of a `ScanBlock` use its `timeaverage` method. Be aware that time averging will not check if the source is the same. \n", "\n", "By default time averaging uses the following weights: \n", "$$\n", "\\frac{T^{2}_{sys}}{\\Delta\\nu\\Delta t}\n", "$$\n", "with $T_{sys}$ the system temperature, $\\Delta\\nu$ the channel width and $\\Delta t$ the integration time. In dysh these are set using `weights=\"tsys\"` (the default)." ] }, { "cell_type": "code", "execution_count": 7, "id": "fd2d612d-a8da-43ff-87d7-b5d6bb266dfd", "metadata": {}, "outputs": [], "source": [ "ta = sbn_scan_block.timeaverage()" ] }, { "cell_type": "markdown", "id": "c0472b5d-9949-42b8-816f-e70ce7b07db8", "metadata": {}, "source": [ "#### Plotting\n", "\n", "Plot the data and use different units for the spectral axis." ] }, { "cell_type": "code", "execution_count": 8, "id": "9d701828-c1d8-4e15-930a-710c09ec1cde", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "be673986e3a5403eba8269301e7488e6", "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": [ "ta.plot(xaxis_unit=\"GHz\");" ] }, { "cell_type": "code", "execution_count": 9, "id": "e0714815-2d9b-4fa4-a181-b5ecc1a64adc", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "9578dd023159445d8fb9e49889025a34", "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": [ "ta.plot(xaxis_unit=\"km/s\", yaxis_unit=\"mK\", ymin=-100, ymax=200);" ] }, { "cell_type": "markdown", "id": "88080556-05cc-4bac-bbca-fc838a8e8352", "metadata": {}, "source": [ "#### Calibration per Scan\n", "The second method (`method=\"scan\"`) of calibrating SubBeamNod scans reproduces the method of GBTIDL's `snodka.pro`. This method treats the entire group of integrations as one cycle. It first time averages all of the integrations on source and off source, and then calibrates using the time averages." ] }, { "cell_type": "code", "execution_count": 10, "id": "3943d577-238e-4d61-99d0-43e8a6137683", "metadata": {}, "outputs": [], "source": [ "sbn_scan_block2 = sdfits.subbeamnod(scan=44, fdnum=1, ifnum=0, plnum=0, method='scan')" ] }, { "cell_type": "code", "execution_count": 11, "id": "2841bb86-3b6c-413b-83cf-303872829db8", "metadata": {}, "outputs": [], "source": [ "ta2 = sbn_scan_block2.timeaverage()" ] }, { "cell_type": "code", "execution_count": 12, "id": "b7d01ea0-237e-40bd-984c-d0db942410dd", "metadata": { "scrolled": true }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "8f9f6e89776f4a99abf37b8d17fe956e", "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": [ "ta2.plot(xaxis_unit=\"GHz\", yaxis_unit=\"mK\", ymin=-100, ymax=200);" ] }, { "cell_type": "code", "execution_count": 13, "id": "0cefeea3-b39c-46ed-8ffc-a5f926658daa", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "5e53b128ffe04fe4ad017e680dd27554", "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" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "deae9641afd04a4db880d6669124bfce", "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" }, { "data": { "text/plain": [ "np.float64(1.263046749396072)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ta[250:750].plot(xaxis_unit=\"chan\").spectrum.radiometer() # 1.2611058840974072\n", "ta2[250:750].plot(xaxis_unit=\"chan\").spectrum.radiometer() # 1.2630467493960695" ] }, { "cell_type": "markdown", "id": "c272edd5-cb66-44bf-b874-bb23c982f46e", "metadata": {}, "source": [ "#### Compare the Two Methods\n" ] }, { "cell_type": "code", "execution_count": 14, "id": "0fa05f47-ec67-40ed-b1af-941af29fde21", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "938763feec5948afae07156a79f88860", "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": [ "(ta2 - ta).plot(xaxis_unit=\"GHz\");" ] }, { "cell_type": "markdown", "id": "84e372ca-7ab6-42dc-872c-2cda24b1a772", "metadata": {}, "source": [ "---------------" ] }, { "cell_type": "markdown", "id": "01aebf80-abb9-4481-9990-5ea6d87de2f1", "metadata": {}, "source": [ "#### Using Selection\n", "\n", "We will repeat the calibration but using selection. First we pre-select the data to be calibrated using the `sdfits.select()` method." ] }, { "cell_type": "code", "execution_count": 15, "id": "b616c8e1-3a0f-4b73-849c-2040a8afa42e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " ID TAG SCAN # SELECTED\n", "--- --------- ---- ----------\n", " 0 929492112 44 1600\n" ] } ], "source": [ "sdfits.select(scan=44)\n", "sdfits.selection.show()" ] }, { "cell_type": "markdown", "id": "1956097c-2f4d-4149-af9d-578b8b7e0065", "metadata": {}, "source": [ "After using selection, the calibration routines will only look for data matching the selection rules. It is also possible to add additional rules for a specific calibration, like the polarization number." ] }, { "cell_type": "code", "execution_count": 16, "id": "31536166-2003-455a-a08a-cf99f0b05381", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "fd7adc4bdb08469d9a0158c9fc633904", "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": [ "sbn_scan_block3 = sdfits.subbeamnod(plnum=0, fdnum=1, ifnum=0)\n", "ta3 = sbn_scan_block3.timeaverage()\n", "ta3.plot(xaxis_unit=\"GHz\");" ] }, { "cell_type": "markdown", "id": "795bd038-8d74-4334-baa8-29d995025026", "metadata": {}, "source": [ "#### Polarization Average\n", "\n", "Now we will calibrate the other polarization and average the two polarizations together.\n", "\n", "First we calibrate the second polarization, then time average it and finally we average them together." ] }, { "cell_type": "code", "execution_count": 17, "id": "5e436f29-5d1d-4162-8710-0f5b6995a18c", "metadata": {}, "outputs": [], "source": [ "sbn_scan_block4 = sdfits.subbeamnod(plnum=1, fdnum=0, ifnum=0)\n", "ta4 = sbn_scan_block4.timeaverage()\n", "pol_avg = ta3.average(ta4)" ] }, { "cell_type": "code", "execution_count": 18, "id": "077aedf7-fac8-4d83-99b7-725e7db0828d", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "3fc55d76d182434ab1f2a74b642ce5b2", "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": [ "pol_avg.plot(xaxis_unit=\"GHz\");" ] }, { "cell_type": "markdown", "id": "14269bfc-752c-4e81-9625-c7dcd4d118a5", "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.\n" ] }, { "cell_type": "code", "execution_count": 19, "id": "ba85340b-accc-4536-a03e-01ac18e0d73c", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "20:09:28.464 I rms is OK (no unit was given, assumed K)\n" ] } ], "source": [ "pol_avg.check_stats(0.03836776)" ] }, { "cell_type": "code", "execution_count": 20, "id": "21639ac2-50ec-44d5-96f3-b904369a71cf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(1.2538633771107333)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pol_avg[250:750].radiometer() # 1.2538633771107366" ] } ], "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" } }, "nbformat": 4, "nbformat_minor": 5 }