{ "cells": [ { "cell_type": "markdown", "id": "7b3aae73", "metadata": {}, "source": [ "[](https://colab.research.google.com/github/nrao/astrohack/blob/v1.0.1/docs/locit_tutorial.ipynb)" ] }, { "cell_type": "markdown", "id": "9151b55a", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "id": "4c6db5ff", "metadata": {}, "source": [ "# Antenna position correction tutorial\n", "\n", "`extract_locit` and `locit` are utilities designed to help determine antenna position shifts after antenna relocation.\n", "To do so they rely on a phase gain calibration table created by `CASA` from antenna pointing data.\n", "The process in `CASA` consists of:\n", "1. `split` out the actual pointing data from the original pointing measurement set (MS), it might contain data taken while the antennas are still slewing.\n", "2. `fringe_fit` the MS using a single source with no delay rates, this is done to flatten a spectral window.\n", "3. `apply_cal` the fringe_fit solution.\n", "4. Channel average the MS using `split`.\n", "5. Compute an average phase gain solution for each source using `gaincal`\n", "\n", "To simplify the process in `CASA` a script is distributed within `astrohack` that the user can simply fill in the parameters for the data reduction and then run it within `CASA`.\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "4beb8248-5a07-4673-82fd-4a74b8f31c38", "metadata": { "ExecuteTime": { "end_time": "2026-02-10T16:59:08.713509785Z", "start_time": "2026-02-10T16:59:06.231728658Z" }, "execution": { "iopub.execute_input": "2026-03-19T21:41:22.431357Z", "iopub.status.busy": "2026-03-19T21:41:22.431210Z", "iopub.status.idle": "2026-03-19T21:41:24.563363Z", "shell.execute_reply": "2026-03-19T21:41:24.562706Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "AstroHACK version 1.0.1 already installed.\n" ] } ], "source": [ "import os\n", "\n", "try:\n", " import astrohack\n", "\n", " print(\"AstroHACK version\", astrohack.__version__, \"already installed.\")\n", "except ImportError as e:\n", " print(e)\n", " print(\"Installing AstroHACK\")\n", "\n", " os.system(\"pip install astrohack\")\n", "\n", " import astrohack\n", "\n", " print(\"astrohack version\", astrohack.__version__, \" installed.\")" ] }, { "cell_type": "markdown", "id": "18bf8960-b27e-48b0-bc54-6ae3bb237f44", "metadata": {}, "source": [ "## Download Tutorial data" ] }, { "cell_type": "code", "execution_count": 2, "id": "aec0ae71-efb0-4f1e-9fe2-29f0dab3b82a", "metadata": { "ExecuteTime": { "end_time": "2026-02-10T16:59:08.850156882Z", "start_time": "2026-02-10T16:59:08.717397817Z" }, "execution": { "iopub.execute_input": "2026-03-19T21:41:24.564792Z", "iopub.status.busy": "2026-03-19T21:41:24.564622Z", "iopub.status.idle": "2026-03-19T21:41:24.829269Z", "shell.execute_reply": "2026-03-19T21:41:24.828732Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[\u001b[38;2;128;05;128m2026-03-19 15:41:24,565\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/export/home/arya/miniforge3/envs/casadev/lib/python3.12/site-packages/toolviper\u001b[0m \n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[\u001b[38;2;128;05;128m2026-03-19 15:41:24,568\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Downloading from [cloudflare] .... \n" ] }, { "data": { "text/html": [ "
\n",
" Download List \n",
" ───────────────────── \n",
" locit-input-pha.cal \n",
" \n",
"\n"
],
"text/plain": [
" \n",
" \u001b[1m \u001b[0m\u001b[1mDownload List \u001b[0m\u001b[1m \u001b[0m \n",
" ───────────────────── \n",
" \u001b[35mlocit-input-pha.cal\u001b[0m \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "3e8d2ad2aec04687ba1eca37ec3515fa",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Output()"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n"
],
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# The Cal table used here is a placeholder, there should be a better dataset to be used with the tutorial\n",
"import toolviper\n",
"\n",
"toolviper.utils.data.download(file=\"locit-input-pha.cal\", folder=\"data\")"
]
},
{
"cell_type": "markdown",
"id": "dbf58722-847f-493c-8963-3985c69b738d",
"metadata": {},
"source": [
"## Position and locit Data File API\n",
"\n",
"As part of the `astroHACK` API a set of functions to allow users to easily open on disk locit and position files has been provided. Each function takes an `astroHACK` locit or position file name as an argument and returns an object related to the given file type. Each object allows the user to access data via dictionary keys with values consisting of the relevant dataset. Each object also provides a `summary()` helper function to list available keys for each file. An example call for each file type is show below and the API documentation for all data-io functions can be found [here](https://astrohack.readthedocs.io/en/latest/_api/autoapi/astrohack/dio/index.html)."
]
},
{
"cell_type": "markdown",
"id": "95cccb50-52bf-4adb-af00-c54c6430c784",
"metadata": {},
"source": [
"```python\n",
"from astrohack import open_locit\n",
"from astrohack import open_position\n",
"\n",
"locit_data = open_locit(file='./data/locit-input-pha.locit.zarr')\n",
"position_data = open_position(file='./data/locit-input-pha.position.zarr')\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "4798fae4-a9c7-4b8f-b6df-f4fa35657e1c",
"metadata": {},
"source": [
"## Setup Dask Local Cluster\n",
"\n",
"The local Dask client handles scheduling and worker managment for the parallelization. The user has the option of choosing the number of cores and memory allocations for each worker howerver, we recommend a minimum of 1Gb per core with standard settings.\n",
"\n",
"\n",
"A significant amount of information related to the client and scheduling can be found using the [Dask Dashboard](https://docs.dask.org/en/stable/dashboard.html). This is a built-in dashboard native to Dask and allows the user to monitor the workers during processing. This is especially useful for profilling. For those that are interested in working soley within Jupyterlab a dashboard extension is available for [Jupyterlab](https://github.com/dask/dask-labextension#dask-jupyterlab-extension).\n",
"\n",
""
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "9dbf9b71",
"metadata": {
"ExecuteTime": {
"end_time": "2026-02-10T16:59:08.904536453Z",
"start_time": "2026-02-10T16:59:08.855428454Z"
},
"execution": {
"iopub.execute_input": "2026-03-19T21:41:24.833905Z",
"iopub.status.busy": "2026-03-19T21:41:24.833784Z",
"iopub.status.idle": "2026-03-19T21:41:25.909038Z",
"shell.execute_reply": "2026-03-19T21:41:25.908512Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[\u001b[38;2;128;05;128m2026-03-19 15:41:24,972\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/export/home/arya/miniforge3/envs/casadev/lib/python3.12/site-packages/toolviper\u001b[0m \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"[\u001b[38;2;128;05;128m2026-03-19 15:41:24,976\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m It is recommended that the local cache directory be set using the \u001b[38;2;50;50;205mdask_local_dir\u001b[0m parameter. \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"[\u001b[38;2;128;05;128m2026-03-19 15:41:25,906\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Client <xarray.DataTree 'ddi_0'>\n",
"Group: /ant_ea06/ddi_0\n",
" Dimensions: (p0_time: 33, p1_time: 34)\n",
" Coordinates:\n",
" * p0_time (p0_time) float64 264B 6.018e+04 6.018e+04 ... 6.018e+04\n",
" * p1_time (p1_time) float64 272B 6.018e+04 6.018e+04 ... 6.018e+04\n",
" Data variables:\n",
" P0_PHASE_GAINS (p0_time) float32 132B 0.2488 0.6855 ... 0.9096 -0.7223\n",
" P0_FIELD_ID (p0_time) int32 132B 0 1 2 3 4 5 6 ... 19 13 25 26 27 28 29\n",
" P1_PHASE_GAINS (p1_time) float32 136B 0.2527 0.6873 ... 0.9876 -0.7128\n",
" P1_FIELD_ID (p1_time) int32 136B 0 1 2 3 4 5 6 ... 19 13 25 26 27 28 29\n",
" Attributes:\n",
" frequency: 8223000000.0\n",
" bandwidth: [128000000.0]\n",
" polarization_scheme: ['R', 'L']<xarray.DataTree 'ant_ea06'>\n",
"Group: /ant_ea06\n",
" Dimensions: (time: 110)\n",
" Coordinates:\n",
" * time (time) float64 880B 0.0 0.002234 0.004711 ... 0.07838 0.07992\n",
" Data variables:\n",
" DECLINATION (time) float64 880B dask.array<chunksize=(110,), meta=np.ndarray>\n",
" DELAYS (time) float32 440B dask.array<chunksize=(110,), meta=np.ndarray>\n",
" ELEVATION (time) float64 880B dask.array<chunksize=(110,), meta=np.ndarray>\n",
" HOUR_ANGLE (time) float64 880B dask.array<chunksize=(110,), meta=np.ndarray>\n",
" LST (time) float64 880B dask.array<chunksize=(110,), meta=np.ndarray>\n",
" MODEL (time) float64 880B dask.array<chunksize=(110,), meta=np.ndarray>\n",
" Attributes:\n",
" antenna_info: {'geocentric_position': [-1602152.0314, -5042031.7101...\n",
" chi_squared: 3.4313971850101646e-23\n",
" elevation_limit: 0.17453292519943295\n",
" fixed_delay_error: 2.133277290921498e-12\n",
" fixed_delay_fit: 2.5331244932983884e-11\n",
" frequency: [8223000000.0, 8823000000.0]\n",
" polarization: both\n",
" position_error: [1.752882019342707e-12, 1.409076320996646e-12, 1.5522...\n",
" position_fit: [-2.989452238023951e-11, -1.2258925779533704e-11, -5....\n",
" rate_error: 2.7610883407111092e-11\n",
" rate_fit: 8.518923662602404e-12locit-input-pha.cal ━━━━━━━━━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━ 38% 0:00:01\n\n", "text/plain": "locit-input-pha.cal \u001b[38;2;249;38;114m━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m 38%\u001b[0m \u001b[36m0:00:01\u001b[0m\n" }, "metadata": {}, "output_type": "display_data" } ], "tabbable": null, "tooltip": null } } }, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 5 }