{ "cells": [ { "cell_type": "markdown", "id": "8c8138ef-e687-444e-95b1-9797654f3f62", "metadata": {}, "source": [ "# Position-Switched Data Reduction\n", "\n", "This notebook shows how to use dysh to calibrate an **OnOff** observation.\n", "It retrieves and calibrates position-switch scans using `GBTFITSLoad.getps`, which returns a `ScanBlock` object. These in turn can be averaged into a `Spectrum`. **OffOn** observations can be reduced the same way.\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.getps()\n", " ta = sb.timeaverage()\n", " ta.baseline()\n", " ta.average()\n", " ta.plot()\n", " ta_plt.savefig()\n", "\n", "\n", "## Loading Modules\n", "We start by loading the modules we will use for the data reduction. " ] }, { "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", "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": "25b4dd7e-e927-4706-afb4-1007d7e0f0b5", "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.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "101396ee-6526-4390-9c06-80422bef85fd", "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. The actual filename will depend on your dysh installation, it could be local, or it will need to be downloaded.\n", "\n", "The [dysh_data](https://dysh.readthedocs.io/en/latest/reference/modules/dysh.util.html#dysh.util.files.dysh_data)\n", "function has a few mnemonics, to avoid having to remember long filenames." ] }, { "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": [ "20:01:58.401 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](https://dysh.readthedocs.io/en/latest/reference/modules/dysh.fits.html#dysh.fits.gbtfitsload.GBTFITSLoad)\n", "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": { "scrolled": true }, "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": "de5497e3-1f36-4976-8749-be86bc6f2e77", "metadata": {}, "source": [ "Here the **PROCSEQN** designates which scan is the \"On\" (1) and which the Off (2). If you like to see more columns, use the `add_columns` argument to `summary`, as we saw in the \n", "[managing metadata](https://dysh.readthedocs.io/en/latest/users_guide/metadata_management.html) notebook." ] }, { "cell_type": "markdown", "id": "e84c5009-96f4-489d-bc9d-89de390d53c9", "metadata": {}, "source": [ "## Data Reduction\n", "\n", "### Single Scan\n", "\n", "Next we calibrate one scan of the position switched observations. We will start with scan 51, a single spectral window, polarization and feed." ] }, { "cell_type": "code", "execution_count": 6, "id": "684126da-97d4-4afb-8625-43160340cab1", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "getps", "test" ] }, "outputs": [], "source": [ "ps_scan_block = sdfits.getps(scan=51, ifnum=0, plnum=0, fdnum=0)" ] }, { "cell_type": "code", "execution_count": 7, "id": "5deaae0c-e70b-4758-ae10-f11c6f66cc3b", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "print_tsys", "test" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "T_sys = 19.36\n" ] } ], "source": [ "print(f\"T_sys = {ps_scan_block[0].tsys.mean():.2f}\")" ] }, { "cell_type": "markdown", "id": "b25c2499-a8c1-434a-b75e-d3bf25e223e7", "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": 8, "id": "e0a33c19-576b-46e8-9a57-f34b8f85f6aa", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "timeaverage", "test" ] }, "outputs": [], "source": [ "ta = ps_scan_block.timeaverage(weights=\"tsys\")" ] }, { "cell_type": "markdown", "id": "38898654-c1da-4a02-91d2-b4f488f18af7", "metadata": {}, "source": [ "#### Plotting\n", "\n", "Plot the data and use different units for the spectral axis. Without any arguments it will auto-scale." ] }, { "cell_type": "code", "execution_count": 9, "id": "40747f0b-d63d-45fa-8910-fef56fe5c751", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "plot1", "test" ] }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "605b4c83913c45dbbb9a6184f01cc069", "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();" ] }, { "cell_type": "markdown", "id": "d83e0206-a79f-44c7-bd2b-a45516720e75", "metadata": {}, "source": [ "Change the spectral axis units to km/s and the y-axis to mK, while also showing the spectra between 3600 and 5300 km/s, with the y-axis range between 0 and 1000 mK. Notice a small amount of \"continuum\" is left, most likely due to the varying sky in this **OnOff** positionswitch observation. We will need to perform a baseline subtraction later on in this notebook." ] }, { "cell_type": "code", "execution_count": 10, "id": "6c07cf19-3a5d-47a9-9a10-ccd9f305efb9", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "plot2", "test" ] }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ee8f7ec18f6e4079ba0e77ea08b6709b", "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=0, ymax=1000, xmin=3600, xmax=5300);" ] }, { "cell_type": "markdown", "id": "1fa13098-104d-42f8-bf16-11d8b46ed0b9", "metadata": {}, "source": [ "Switch to channels as the spectral axis unit. \n", "\n", "Notice we are also returning a plotter object (`plt1`) so we can save it later with as baseline fit." ] }, { "cell_type": "code", "execution_count": 11, "id": "5fa6773c-b8e1-45ee-867c-b044df994f91", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "af64a37ae27e4848a83afe266084cd0f", "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": [ "plt1 = ta.plot(xaxis_unit=\"chan\", ymin=0, ymax=1000, yaxis_unit=\"mK\")" ] }, { "cell_type": "markdown", "id": "0988ba2f-7ed0-4386-b4a5-7635537b8c5f", "metadata": {}, "source": [ "#### Baseline Subtraction\n", "The following code cells show how to subtract a polynomial baseline from the data. This example uses an 2nd order polynomial, and excludes the regions between 3800 and 5000 km/s, where a line is detected. The use of `remove=True` will remove the best fit baseline model from the spectrum, but by default the baseline is not subtracted. This will show that plotting the spectrum will also display the fitted baseline. (caveat: only the last plot before the baseline fit).\n", "\n", "For a polynomial model one may need to normalize the frequency axis in channel space using `normalize=True`, to prevent poorly conditioned fits, but this will not allow you to undo the fit." ] }, { "cell_type": "code", "execution_count": 12, "id": "d4c4526b-2e78-4f0f-85ff-0a4e3694a1e5", "metadata": { "editable": true, "scrolled": true, "slideshow": { "slide_type": "" }, "tags": [ "baseline", "test" ] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "20:01:59.320 I EXCLUDING [Spectral Region, 1 sub-regions:\n", " (1397103816.4779327 Hz, 1402626103.134255 Hz) \n", "]\n" ] } ], "source": [ "kms = u.km/u.s\n", "ta.baseline(model=\"poly\", degree=2, exclude=[3800*kms,5000*kms]) \n", "# saving the plot will also show the baseline fit\n", "plt1.savefig(output_dir / \"plt1.png\")\n" ] }, { "cell_type": "markdown", "id": "fa0eff29-f4c2-40e1-a758-cbeab24f2c15", "metadata": {}, "source": [ "Notice that in interactive mode you would see the fitted baseline in the spectrum plot before. But in normal notebook mode, the figure needs to be saved explicitly. Re-executing the cell will overplot new baseline fits.\n", "\n", "Now remove the baseline for sure. Again, this is not the default." ] }, { "cell_type": "code", "execution_count": 13, "id": "502c0677-011d-44c0-95b9-3bb1f296b9ca", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "20:01:59.511 I EXCLUDING [Spectral Region, 1 sub-regions:\n", " (1397103816.4779327 Hz, 1402626103.134255 Hz) \n", "]\n" ] } ], "source": [ "ta.baseline(model=\"poly\", degree=2, exclude=[3800*kms,5000*kms], remove=True)" ] }, { "cell_type": "markdown", "id": "5ac09df0-0025-4bef-a779-b9896f5232fd", "metadata": {}, "source": [ "As an aside, exluding the obvious signal for NGC5291, will however include the edges, and the galactic emission around 0 km/s. It would be better to use the `include=` keyword and give a list of two intervals, for example 500 to 3800 and 5000 to 9000 km/s. We leave this as an exersize for the reader. You should find a difference of about 7 mK between the two solutions.\n", "\n", "When we plot the spectrum again, it has been baseline subtracted." ] }, { "cell_type": "code", "execution_count": 14, "id": "43a07117-7088-43e5-927c-0c7ead1eb4fd", "metadata": { "scrolled": true }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "970b09e7b983453f86214238e03618f5", "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": [ "plt2 = ta.plot(xaxis_unit=\"km/s\", yaxis_unit=\"mK\", ymin=-500, ymax=500)" ] }, { "cell_type": "markdown", "id": "57f451bc-f27e-4e69-a735-009fedaf68f1", "metadata": {}, "source": [ "We can inspect the best fit baseline coefficients." ] }, { "cell_type": "code", "execution_count": 15, "id": "219e21a8-91cb-405e-82fc-249143c219ae", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "test" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "print(ta.baseline_model)" ] }, { "cell_type": "markdown", "id": "01f5ca58-05ad-4124-8527-40ab2cd073fa", "metadata": {}, "source": [ "And save the figure, now without a baseline fit of course." ] }, { "cell_type": "code", "execution_count": 16, "id": "3a7e4887-ba55-447a-9274-8275e9896d39", "metadata": {}, "outputs": [], "source": [ "plt2.savefig(output_dir / \"baselined_removed.png\")" ] }, { "cell_type": "markdown", "id": "0f15fa5c-41cb-42e7-ac5c-79574f9a4465", "metadata": {}, "source": [ "If for some reason you are not happy, use the `ta.undo_baseline()` function to restore the Spectrum data and delete the baseline model. You can then start with a new baseline fit." ] }, { "cell_type": "markdown", "id": "3462f31f-f69e-48db-96f5-33f4071a384b", "metadata": {}, "source": [ "#### Using Selection\n", "\n", "The following code shows how to calibrate scan 51 using selection. Selection does not know about signal and reference scan pairs, so the selection must include both scans, otherwise the calibration will fail." ] }, { "cell_type": "code", "execution_count": 17, "id": "1786d5c3-3701-4199-b4a3-80a14dc92f5b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " ID TAG SCAN # SELECTED\n", "--- --------- ------- ----------\n", " 0 acd6828d9 [51,52] 88\n" ] } ], "source": [ "sdfits.select(scan=[51,52])\n", "sdfits.selection.show()" ] }, { "cell_type": "code", "execution_count": 18, "id": "56e22004-a5cd-4064-a1eb-edaf6afe88f4", "metadata": {}, "outputs": [], "source": [ "sb = sdfits.getps(plnum=0, ifnum=0, fdnum=0)" ] }, { "cell_type": "code", "execution_count": 19, "id": "4281fdea-ab00-47e5-aca0-cc23b43224a7", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "f8e543ff455c4a15bfd11a0e27284ef6", "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 = sb.timeaverage(weights='tsys')\n", "ta2.plot(xaxis_unit=\"GHz\", ymin=-100, ymax=800, yaxis_unit=\"mK\", title=\"PLNUM=0\");" ] }, { "cell_type": "markdown", "id": "e7a4ef5f-2bf3-4bfc-8177-8a7ad793b014", "metadata": {}, "source": [ "We can calibrate the other polarization, with the scan numbers already selected." ] }, { "cell_type": "code", "execution_count": 20, "id": "6a1bff52-fc5c-437e-9da0-787f17029b77", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "41ab155443434b92af9f59151743a22e", "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": [ "sb = sdfits.getps(plnum=1, fdnum=0, ifnum=0)\n", "ta3 = sb.timeaverage(weights='tsys')\n", "ta3.plot(xaxis_unit=\"GHz\", ymin=-100, ymax=800, yaxis_unit=\"mK\", title=\"PLNUM=1\");" ] }, { "cell_type": "markdown", "id": "339576f4-7317-4791-aca4-b52f9f8f1153", "metadata": {}, "source": [ "#### Polarization Average\n", "Average the polarizations and plot the result." ] }, { "cell_type": "code", "execution_count": 21, "id": "6f9c51ab-7a04-4def-b8f8-58f6cb308660", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "391f72f693b74a1b992086c99ca69aa8", "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": [ "avg = ta2.average(ta3)\n", "avg.plot(ymin=-100, ymax=800, yaxis_unit=\"mK\", xaxis_unit=\"GHz\");" ] }, { "cell_type": "markdown", "id": "387bc886-512b-490f-9bd0-ade391e08327", "metadata": {}, "source": [ "### All Scans\n", "\n", "Now we leverage the power of dysh to calibrate and time average all of the scans in the data.\n", "\n", "We start by clearing the selection, so all of the scans are available." ] }, { "cell_type": "code", "execution_count": 22, "id": "56a50d07-ea90-4c46-990f-012d3f7a733c", "metadata": {}, "outputs": [], "source": [ "sdfits.clear_selection()" ] }, { "cell_type": "markdown", "id": "4d1a49f2-8279-4b26-b4c4-9e69ca7ed569", "metadata": {}, "source": [ "Then, make a `ScanBlock` for spectral window 0, polarization 0, and feed 0. Time average the scans in the `ScanBlock` into a single `Spectrum` and then remove a baseline." ] }, { "cell_type": "code", "execution_count": 23, "id": "b11a2291-9cfd-40c4-9450-9f4e056155e4", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "20:02:01.222 I EXCLUDING [Spectral Region, 1 sub-regions:\n", " (1397103816.4779327 Hz, 1402626103.134255 Hz) \n", "]\n" ] } ], "source": [ "ps_scan_block_0 = sdfits.getps(ifnum=0, plnum=0, fdnum=0)\n", "ps_ta_0 = ps_scan_block_0.timeaverage(weights='tsys')\n", "ps_ta_0.baseline(model=\"poly\", degree=2, exclude=[3800*kms,5000*kms], remove=True)" ] }, { "cell_type": "markdown", "id": "3bcf3877-5398-4225-8d51-6833e89acd0b", "metadata": {}, "source": [ "Now plot and compare with the result for a single scan." ] }, { "cell_type": "code", "execution_count": 24, "id": "1ead1ef4-61eb-4080-801d-e0728990674a", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ade8e9b18dd54cf08ba96f4608b59f60", "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": "33d26af8155943d9b96bdf8ed6cc8452", "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(ymin=-400, ymax=400, yaxis_unit=\"mK\", xaxis_unit=\"GHz\")\n", "ps_ta_0.plot(ymin=-400, ymax=400, yaxis_unit=\"mK\", xaxis_unit=\"GHz\");" ] }, { "cell_type": "markdown", "id": "f10227ec-47c2-4a92-bc80-ad3a69b9d648", "metadata": {}, "source": [ "The rms in the second Figure is almost half that of the first Figure. That is because there are four pairs of position switched scans in the data, so that results in a factor of $\\sqrt{4}$ reduced noise when we average all the data." ] }, { "cell_type": "markdown", "id": "ccd9ac27-2783-42d2-bdf3-aca28fa9866c", "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": 25, "id": "8a12633b-ed26-44ec-bf55-2ad4ee59e546", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "20:02:01.370 I rms is OK \n" ] } ], "source": [ "ps_ta_0.check_stats(0.06010087 * u.K)" ] } ], "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 }