diff --git a/.gitignore b/.gitignore index 6aaec371..9cae4f8a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ docs/_build/ _version.py _autosummary/ coverage.xml +.ipynb_checkpoints/ diff --git a/docs/conf.py b/docs/conf.py index 15107226..26db6d57 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,9 +1,10 @@ """Configuration for docs.""" import os -from datetime import datetime, timezone import sys +from datetime import UTC, datetime from pathlib import Path + sys.path.insert(0, str(Path(__file__).absolute().parent.parent / "src")) import tuesday @@ -45,7 +46,7 @@ source_suffix = ".rst" master_doc = "index" project = "tuesday" -year = str(datetime.now(tz=timezone.utc).year) +year = str(datetime.now(tz=UTC).year) author = "Daniela Breitman and Steven Murray" copyright = f"{year}, {author}" version = release = tuesday.__version__ @@ -86,4 +87,4 @@ ".DS_Store", "templates", "**.ipynb_checkpoints", -] \ No newline at end of file +] diff --git a/docs/tutorials/computing_and_plotting_power_spectra.ipynb b/docs/tutorials/computing_and_plotting_power_spectra.ipynb index aa250b41..796fbf5c 100644 --- a/docs/tutorials/computing_and_plotting_power_spectra.ipynb +++ b/docs/tutorials/computing_and_plotting_power_spectra.ipynb @@ -185,14 +185,13 @@ } ], "source": [ - "\n", "ax = plot_coeval_slice(\n", " delta_x,\n", " box_len,\n", " transform2slice=coeval2slice_x(idx=15),\n", " title=\"Slice in x-direction\",\n", - " v_x=delta_x[15,...]*un.m / un.s,\n", - " v_y=delta_x[15,...]*un.m / un.s,\n", + " v_x=delta_x[15, ...] * un.m / un.s,\n", + " v_y=delta_x[15, ...] * un.m / un.s,\n", " quiver_decimate_factor=3,\n", ")" ] @@ -232,7 +231,10 @@ ], "source": [ "plot_coeval_slice(\n", - " delta_x.value*un.mK, box_len, transform2slice=coeval2slice_y(), title=\"Slice in y-direction\"\n", + " delta_x.value * un.mK,\n", + " box_len,\n", + " transform2slice=coeval2slice_y(),\n", + " title=\"Slice in y-direction\",\n", ")" ] }, @@ -530,16 +532,16 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "from tuesday.core import lc2slice_x, lc2slice_y, plot_redshift_slice" + "from tuesday.core import lc2slice_x, lc2slice_y, plot_lightcone_slice" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -564,7 +566,7 @@ } ], "source": [ - "plot_redshift_slice(\n", + "plot_lightcone_slice(\n", " lc,\n", " box_len,\n", " lc_redshifts,\n", @@ -583,7 +585,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -608,7 +610,7 @@ } ], "source": [ - "plot_redshift_slice(\n", + "plot_lightcone_slice(\n", " lc,\n", " box_len,\n", " lc_redshifts,\n", @@ -628,7 +630,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -653,7 +655,7 @@ } ], "source": [ - "plot_redshift_slice(\n", + "plot_lightcone_slice(\n", " lc,\n", " box_len,\n", " lc_redshifts,\n", @@ -793,16 +795,16 @@ "fig, ax = plt.subplots(1, 1, figsize=(18, 7))\n", "\n", "ax = tuesday.core.plot_power_spectrum(\n", - " ps1d,\n", - " at_k=0.05,\n", - " fontsize=20,\n", - " ax=ax,\n", - " color=f\"r\",\n", - " legend=f\"k ~ 0.05\",\n", - " legend_kwargs={\"frameon\": False},\n", - " logx=False,\n", - " logy=False,\n", - " )\n", + " ps1d,\n", + " at_k=0.05,\n", + " fontsize=20,\n", + " ax=ax,\n", + " color=\"r\",\n", + " legend=\"k ~ 0.05\",\n", + " legend_kwargs={\"frameon\": False},\n", + " logx=False,\n", + " logy=False,\n", + ")\n", "\n", "ax = tuesday.core.plot_power_spectrum(\n", " all_analytic,\n", @@ -840,16 +842,16 @@ "fig, ax = plt.subplots(1, 1, figsize=(18, 7))\n", "\n", "ax = tuesday.core.plot_power_spectrum(\n", - " ps1d,\n", - " fontsize=20,\n", - " ax=ax,\n", - " color=f\"r\",\n", - " at_k=at_k,\n", - " legend=f\"k ~ \"+str(at_k),\n", - " legend_kwargs={\"frameon\": False},\n", - " logx=False,\n", - " logy=False,\n", - " )\n", + " ps1d,\n", + " fontsize=20,\n", + " ax=ax,\n", + " color=\"r\",\n", + " at_k=at_k,\n", + " legend=\"k ~ \" + str(at_k),\n", + " legend_kwargs={\"frameon\": False},\n", + " logx=False,\n", + " logy=False,\n", + ")\n", "\n", "ax = tuesday.core.plot_power_spectrum(\n", " all_analytic,\n", @@ -1064,7 +1066,7 @@ ], "metadata": { "kernelspec": { - "display_name": "21cmFAST", + "display_name": "tuesday", "language": "python", "name": "python3" }, @@ -1078,7 +1080,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.12" + "version": "3.12.6" }, "latex_envs": { "LaTeX_envs_menu_present": true, diff --git a/docs/tutorials/lc_noise_compare_tools21cm.ipynb b/docs/tutorials/lc_noise_compare_tools21cm.ipynb index b650063c..6b147bca 100644 --- a/docs/tutorials/lc_noise_compare_tools21cm.ipynb +++ b/docs/tutorials/lc_noise_compare_tools21cm.ipynb @@ -2,6 +2,7 @@ "cells": [ { "cell_type": "markdown", + "id": "7fb27b941602401d91542211134fc71a", "metadata": {}, "source": [ "# Generating lightcone noise samples - Comparing between `tuesday` and `tools21cm`\n", @@ -13,43 +14,52 @@ { "cell_type": "code", "execution_count": 1, + "id": "acae54e37e7d407bbb7b55eff062a284", "metadata": {}, "outputs": [], "source": [ + "import astropy.units as un\n", + "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "from py21cmsense import Observatory, Observation\n", + "from py21cmsense import Observation, Observatory\n", "from py21cmsense.conversions import f2z\n", - "import astropy.units as un\n", - "\n", - "from tools21cm.radio_telescope_noise import get_uv_map, get_SKA_Low_layout\n", - "import matplotlib.pyplot as plt" + "from tools21cm.radio_telescope_noise import get_SKA_Low_layout, get_uv_map" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, + "id": "9a63283cbaf04dbcab1f6479b197f3a8", "metadata": {}, "outputs": [], "source": [ - "def compare(tools_qt, tuesday_qt, qt_name=\"\", f = \"150 MHz\", vmin=None, vmax=None):\n", - " fig, axs = plt.subplots(1, 3, figsize=(12, 6), gridspec_kw={\"width_ratios\":[1,1,0.07]})\n", + "def compare(tools_qt, tuesday_qt, qt_name=\"\", f=\"150 MHz\", vmin=None, vmax=None):\n", + " \"\"\"Perform a quick comparison between tools21cm and tuesday quantities.\"\"\"\n", + " fig, axs = plt.subplots(\n", + " 1, 3, figsize=(12, 6), gridspec_kw={\"width_ratios\": [1, 1, 0.07]}\n", + " )\n", " if vmin is None:\n", " vmin = np.nanpercentile(tools_qt, 2.5)\n", " if vmax is None:\n", " vmax = np.nanpercentile(tools_qt, 97.5)\n", " axs[0].set_title(f\"tuesday - {qt_name} at {f} for SKA AA4\")\n", - " axs[0].imshow(np.flip(tuesday_qt.T), origin=\"lower\", vmin = vmin, vmax = vmax)\n", + " axs[0].imshow(np.flip(tuesday_qt.T), origin=\"lower\", vmin=vmin, vmax=vmax)\n", " axs[1].set_title(f\"tools21cm - {qt_name} at {f} for SKA AA4\")\n", - " im=axs[1].imshow(tools_qt.T, origin=\"lower\", vmin = vmin, vmax = vmax)\n", - " fig.colorbar(im, label = qt_name, cax = axs[2],fraction=0.1,shrink=0.6)\n", + " im = axs[1].imshow(tools_qt.T, origin=\"lower\", vmin=vmin, vmax=vmax)\n", + " fig.colorbar(im, label=qt_name, cax=axs[2], fraction=0.1, shrink=0.6)\n", " plt.show()\n", " err = tools_qt.T - np.flip(tuesday_qt.T)\n", " vmin = np.nanpercentile(err, 2.5)\n", " vmax = np.nanpercentile(err, 97.5)\n", - " fig, axs = plt.subplots(1,2, figsize=(12, 6))\n", - " im = axs[0].imshow(err, vmin = vmin, vmax = vmax, origin=\"lower\")\n", - " fig.colorbar(im, label = f\"tools21cm {qt_name} - 21cmSense {qt_name}\", fraction=0.1,shrink=0.8)\n", - " axs[1].hist(err.ravel(), bins = np.linspace(vmin,vmax,20))\n", + " fig, axs = plt.subplots(1, 2, figsize=(12, 6))\n", + " im = axs[0].imshow(err, vmin=vmin, vmax=vmax, origin=\"lower\")\n", + " fig.colorbar(\n", + " im,\n", + " label=f\"tools21cm {qt_name} - 21cmSense {qt_name}\",\n", + " fraction=0.1,\n", + " shrink=0.8,\n", + " )\n", + " axs[1].hist(err.ravel(), bins=np.linspace(vmin, vmax, 20))\n", " axs[1].set_xlabel(f\"tools21cm {qt_name} - 21cmSense {qt_name}\")\n", " plt.show()" ] @@ -70,7 +80,7 @@ "metadata": {}, "outputs": [], "source": [ - "hours_tracking = 6.*un.hour\n", + "hours_tracking = 6.0 * un.hour\n", "observatory = Observatory.from_ska(\"AA4\")\n", "freqs = np.array([150.0, 250.0]) * un.MHz" ] @@ -111,8 +121,14 @@ } ], "source": [ - "plt.scatter(enu_coords[:,0], enu_coords[:,1], color = \"k\", label = \"tools21cm\")\n", - "plt.scatter(observatory.antpos[:,0], observatory.antpos[:,1], color = \"r\", marker = \".\", label = \"tuesday\")\n", + "plt.scatter(enu_coords[:, 0], enu_coords[:, 1], color=\"k\", label=\"tools21cm\")\n", + "plt.scatter(\n", + " observatory.antpos[:, 0],\n", + " observatory.antpos[:, 1],\n", + " color=\"r\",\n", + " marker=\".\",\n", + " label=\"tuesday\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -137,8 +153,10 @@ "outputs": [], "source": [ "observatory = observatory.clone(beam=observatory.beam.clone(frequency=freqs[0]))\n", - "integration_time = 60*un.s\n", - "time_offsets = observatory.time_offsets_from_obs_int_time(integration_time, hours_tracking)" + "integration_time = 60 * un.s\n", + "time_offsets = observatory.time_offsets_from_obs_int_time(\n", + " integration_time, hours_tracking\n", + ")" ] }, { @@ -203,8 +221,10 @@ "metadata": {}, "outputs": [], "source": [ - "proj_bls = observatory.projected_baselines(baselines=baselines, #21cmsense caches them \n", - " time_offset = time_offsets, ) #(Nbls, N time_offsets, 3)" + "proj_bls = observatory.projected_baselines(\n", + " baselines=baselines, # 21cmsense caches them\n", + " time_offset=time_offsets,\n", + ") # (Nbls, N time_offsets, 3)" ] }, { @@ -227,8 +247,8 @@ "metadata": {}, "outputs": [], "source": [ - "lc_shape = np.array([200,200,1945])\n", - "boxlength = 300. *un.Mpc" + "lc_shape = np.array([200, 200, 1945])\n", + "boxlength = 300.0 * un.Mpc" ] }, { @@ -246,14 +266,12 @@ "metadata": {}, "outputs": [], "source": [ - "uv_coverage = np.zeros((lc_shape[0],lc_shape[0],len(freqs)))#Nu, Nv, Nfreqs\n", - "for i, freq in enumerate(freqs): \n", + "uv_coverage = np.zeros((lc_shape[0], lc_shape[0], len(freqs))) # Nu, Nv, Nfreqs\n", + "for i, freq in enumerate(freqs):\n", " # uv coverage integrated over one field\n", - " uv_coverage[...,i] += grid_baselines_uv(proj_bls[::2]*freq/freqs[0],\n", - " freq,\n", - " boxlength, \n", - " lc_shape,\n", - " weights[::2])" + " uv_coverage[..., i] += grid_baselines_uv(\n", + " proj_bls[::2] * freq / freqs[0], freq, boxlength, lc_shape, weights[::2]\n", + " )" ] }, { @@ -321,14 +339,19 @@ "source": [ "redshifts = [f2z(freq) for freq in freqs]\n", "uv_tools = np.zeros_like(uv_coverage)\n", - "for i,z in enumerate(redshifts):\n", - " uv, Nant = get_uv_map(lc_shape[0],z, \n", - " boxsize=boxlength.value,\n", - " int_time=integration_time.value,\n", - " total_int_time= hours_tracking.value,\n", - " include_mirror_baselines=True,\n", - " declination = -26.824722)\n", - " uv_tools[...,i] = np.fft.fftshift(uv)*int(3600*hours_tracking.value/integration_time.value)" + "for i, z in enumerate(redshifts):\n", + " uv, Nant = get_uv_map(\n", + " lc_shape[0],\n", + " z,\n", + " boxsize=boxlength.value,\n", + " int_time=integration_time.value,\n", + " total_int_time=hours_tracking.value,\n", + " include_mirror_baselines=True,\n", + " declination=-26.824722,\n", + " )\n", + " uv_tools[..., i] = np.fft.fftshift(uv) * int(\n", + " 3600 * hours_tracking.value / integration_time.value\n", + " )" ] }, { @@ -367,7 +390,7 @@ } ], "source": [ - "compare(uv_tools[...,0], uv_coverage[...,0], \"uv coverage\", f = \"150 MHz\")" + "compare(uv_tools[..., 0], uv_coverage[..., 0], \"uv coverage\", f=\"150 MHz\")" ] }, { @@ -398,11 +421,12 @@ } ], "source": [ - "compare(uv_tools[...,1], uv_coverage[...,1], \"uv coverage\", f = \"250 MHz\")" + "compare(uv_tools[..., 1], uv_coverage[..., 1], \"uv coverage\", f=\"250 MHz\")" ] }, { "cell_type": "markdown", + "id": "8dd0d8092fe74a7c96281538738b07e2", "metadata": {}, "source": [ "## Calculate the thermal RMS noise with `tuesday`\n", @@ -413,6 +437,7 @@ { "cell_type": "code", "execution_count": 15, + "id": "72eea5119410473aa328ad9291626812", "metadata": {}, "outputs": [], "source": [ @@ -422,35 +447,41 @@ { "cell_type": "code", "execution_count": 16, + "id": "8edb47106e1a46a883d545849b8ab81b", "metadata": {}, "outputs": [], "source": [ "# Define an observation\n", - "obs = Observation(observatory=observatory.clone(beam=observatory.beam.clone(frequency=freqs[0])), \n", - " time_per_day=hours_tracking,\n", - " lst_bin_size=hours_tracking,\n", - " integration_time=integration_time,\n", - " bandwidth=50 *un.kHz,\n", - " n_days=int(np.ceil(1000/hours_tracking.value)),\n", - " tsky_amplitude=60.*un.K, # to be consistent with tools21cm\n", - " tsky_ref_freq=300.*un.MHz,\n", - " spectral_index=2.55,\n", - " )" + "obs = Observation(\n", + " observatory=observatory.clone(beam=observatory.beam.clone(frequency=freqs[0])),\n", + " time_per_day=hours_tracking,\n", + " lst_bin_size=hours_tracking,\n", + " integration_time=integration_time,\n", + " bandwidth=50 * un.kHz,\n", + " n_days=int(np.ceil(1000 / hours_tracking.value)),\n", + " tsky_amplitude=60.0 * un.K, # to be consistent with tools21cm\n", + " tsky_ref_freq=300.0 * un.MHz,\n", + " spectral_index=2.55,\n", + ")" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, + "id": "10185d26023b46108eb7d9f57d49d2b3", "metadata": {}, "outputs": [], "source": [ - "sigmaN_rms = thermal_noise_per_voxel(obs, freqs, boxlength, lc_shape, antenna_effective_area = [517.7, 186.4]*un.m**2) #A_eff set to match tools21cm\n", - "sigmaN = sigmaN_rms / np.sqrt(uv_coverage * obs.n_days)\n", - "sigmaN[uv_coverage == 0.] = 0." + "sigma_rms = thermal_noise_per_voxel(\n", + " obs, freqs, boxlength, lc_shape, antenna_effective_area=[517.7, 186.4] * un.m**2\n", + ") # A_eff set to match tools21cm\n", + "sigma = sigma_rms / np.sqrt(uv_coverage * obs.n_days)\n", + "sigma[uv_coverage == 0.0] = 0.0" ] }, { "cell_type": "markdown", + "id": "8763a12b2bbd4a93a75aff182afb95dc", "metadata": {}, "source": [ "## Calculate thermal RMS noise with tools21cm" @@ -459,16 +490,18 @@ { "cell_type": "code", "execution_count": 18, + "id": "7623eae2785240b9bd12b16a66d81610", "metadata": {}, "outputs": [], "source": [ - "from tools21cm.radio_telescope_sensitivity import sigma_noise_radio, jansky_2_kelvin, kelvin_2_jansky\n", - "from tools21cm.radio_telescope_noise import noise_map" + "from tools21cm.radio_telescope_noise import noise_map\n", + "from tools21cm.radio_telescope_sensitivity import jansky_2_kelvin, sigma_noise_radio" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, + "id": "7cdc8c89c7104fffa095e18ddfef8986", "metadata": {}, "outputs": [ { @@ -489,24 +522,29 @@ } ], "source": [ - "sigmaN_tools = np.zeros((lc_shape[0],lc_shape[0],len(freqs)))#Nu, Nv, Nfreqs\n", - "sigmaN_rms_tools = np.zeros(len(freqs))\n", + "sigma_tools = np.zeros((lc_shape[0], lc_shape[0], len(freqs))) # Nu, Nv, Nfreqs\n", + "sigma_rms_tools = np.zeros(len(freqs))\n", "\n", - "for i, freq in enumerate(freqs): \n", - " sigma, rms_noi = sigma_noise_radio(f2z(freq), \n", - " obs.bandwidth.to(un.MHz).value, \n", - " obs.n_days*obs.time_per_day.value, \n", - " integration_time.value, \n", - " uv_map=uv_tools, \n", - " N_ant=512) #μJy\n", - " sigmaN_rms_tools[i] = jansky_2_kelvin(rms_noi*1e-6, f2z(freq), boxsize=boxlength.value, ncells=lc_shape[0])[0] #mK\n", - " print(\"RMS tools21cm\",sigmaN_rms_tools[i], \"vs RMS tuesday\", sigmaN_rms[i])\n", - " sigmaN_tools[...,i] = sigmaN_rms_tools[i] / np.sqrt(uv_tools[...,i] * obs.n_days)\n", - "sigmaN_tools[uv_tools == 0.] = 0." + "for i, freq in enumerate(freqs):\n", + " sigma, rms_noi = sigma_noise_radio(\n", + " f2z(freq),\n", + " obs.bandwidth.to(un.MHz).value,\n", + " obs.n_days * obs.time_per_day.value,\n", + " integration_time.value,\n", + " uv_map=uv_tools,\n", + " N_ant=512,\n", + " ) # μJy\n", + " sigma_rms_tools[i] = jansky_2_kelvin(\n", + " rms_noi * 1e-6, f2z(freq), boxsize=boxlength.value, ncells=lc_shape[0]\n", + " )[0] # mK\n", + " print(\"RMS tools21cm\", sigma_rms_tools[i], \"vs RMS tuesday\", sigma_rms[i])\n", + " sigma_tools[..., i] = sigma_rms_tools[i] / np.sqrt(uv_tools[..., i] * obs.n_days)\n", + "sigma_tools[uv_tools == 0.0] = 0.0" ] }, { "cell_type": "markdown", + "id": "b118ea5561624da68c537baed56e602f", "metadata": {}, "source": [ "## Compare the thermal RMS noise" @@ -514,7 +552,8 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, + "id": "938c804e27f84196a10c8828c723f798", "metadata": {}, "outputs": [ { @@ -539,12 +578,13 @@ } ], "source": [ - "compare(sigmaN_tools[...,0], sigmaN[...,0].value, r\"$\\sigma_{N}$ [mK]\")" + "compare(sigma_tools[..., 0], sigma[..., 0].value, r\"$\\sigma_{N}$ [mK]\")" ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, + "id": "504fb2a444614c0babb325280ed9130a", "metadata": {}, "outputs": [ { @@ -569,11 +609,12 @@ } ], "source": [ - "compare(sigmaN_tools[...,1], sigmaN[...,1].value, r\"$\\sigma_{N}$ [mK]\", f=\"250 MHz\")" + "compare(sigma_tools[..., 1], sigma[..., 1].value, r\"$\\sigma_{N}$ [mK]\", f=\"250 MHz\")" ] }, { "cell_type": "markdown", + "id": "59bbdb311c014d738909a11f9e486628", "metadata": {}, "source": [ "## Sample lightcone noise with `tools21cm`\n", @@ -583,15 +624,15 @@ { "cell_type": "code", "execution_count": 22, + "id": "b43b363d81ae4b689946ece5c682cd59", "metadata": {}, "outputs": [], - "source": [ - "from tools21cm.radio_telescope_noise import noise_map" - ] + "source": [] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, + "id": "8a65eabff63a45729fe45fb5ade58bdc", "metadata": {}, "outputs": [ { @@ -643,22 +684,33 @@ } ], "source": [ - "noise_tools = np.zeros_like(sigmaN)\n", - "for i, freq in enumerate(freqs): \n", - " n = noise_map(lc_shape[0], \n", - " f2z(freq), \n", - " obs.bandwidth.to(un.MHz).value, \n", - " obs_time=obs.n_days*obs.time_per_day.value, \n", - " subarray_type=\"AA4\", \n", - " boxsize=boxlength.value, \n", - " total_int_time=obs.time_per_day.value, \n", - " int_time=integration_time.value, \n", - " declination=-26.824722,)*un.uJy\n", - " noise_tools[...,i] = jansky_2_kelvin(n.to(un.Jy).value, f2z(freq), boxsize=boxlength.value, ncells=lc_shape[0])*un.mK" + "noise_tools = np.zeros_like(sigma)\n", + "for i, freq in enumerate(freqs):\n", + " n = (\n", + " noise_map(\n", + " lc_shape[0],\n", + " f2z(freq),\n", + " obs.bandwidth.to(un.MHz).value,\n", + " obs_time=obs.n_days * obs.time_per_day.value,\n", + " subarray_type=\"AA4\",\n", + " boxsize=boxlength.value,\n", + " total_int_time=obs.time_per_day.value,\n", + " int_time=integration_time.value,\n", + " declination=-26.824722,\n", + " )\n", + " * un.uJy\n", + " )\n", + " noise_tools[..., i] = (\n", + " jansky_2_kelvin(\n", + " n.to(un.Jy).value, f2z(freq), boxsize=boxlength.value, ncells=lc_shape[0]\n", + " )\n", + " * un.mK\n", + " )" ] }, { "cell_type": "markdown", + "id": "c3933fab20d04ec698c2621248eb3be0", "metadata": {}, "source": [ "## Sample lightcone noise with `tuesday`\n", @@ -669,6 +721,7 @@ { "cell_type": "code", "execution_count": 24, + "id": "4dd4641cc4064e0191573fe9c69df29b", "metadata": {}, "outputs": [], "source": [ @@ -677,17 +730,17 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, + "id": "8309879909854d7188b41380fd92a7c3", "metadata": {}, "outputs": [], "source": [ - "noise = sample_lc_noise(sigmaN, \n", - " seed=4, \n", - " nsamples=10)" + "noise = sample_lc_noise(sigma, seed=4, nsamples=10)" ] }, { "cell_type": "markdown", + "id": "3ed186c9a28b402fb0bc4494df01f08d", "metadata": {}, "source": [ "## Compare noise realisations" @@ -696,6 +749,7 @@ { "cell_type": "code", "execution_count": 26, + "id": "cb1e1581032b452c9409d6c6813c49d1", "metadata": {}, "outputs": [ { @@ -720,12 +774,13 @@ } ], "source": [ - "compare(noise_tools.value[...,0], noise[2,...,0].value, \"noise [mK]\")" + "compare(noise_tools.value[..., 0], noise[2, ..., 0].value, \"noise [mK]\")" ] }, { "cell_type": "code", "execution_count": 27, + "id": "379cbbc1e968416e875cc15c1202d7eb", "metadata": {}, "outputs": [ { @@ -750,12 +805,13 @@ } ], "source": [ - "compare(noise_tools.value[...,1], noise[0,...,1].value, \"noise [mK]\", f=\"250 MHz\")" + "compare(noise_tools.value[..., 1], noise[0, ..., 1].value, \"noise [mK]\", f=\"250 MHz\")" ] }, { "cell_type": "code", "execution_count": null, + "id": "277c27b1587741f2af2001be3712ef0d", "metadata": {}, "outputs": [], "source": [] diff --git a/pyproject.toml b/pyproject.toml index 3d2a1da2..3d59f0e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ dependencies = [ "numpy>=2", "powerbox>=0.8.2", "scipy>=1.15.2", + "deprecation", ] dynamic = ['version'] diff --git a/src/tuesday/__init__.py b/src/tuesday/__init__.py index 2c97ffd0..c2e258f6 100644 --- a/src/tuesday/__init__.py +++ b/src/tuesday/__init__.py @@ -1,7 +1,6 @@ """The Ultimate EoR Simulation Data AnalYser (TUESDAY) package.""" __all__ = ["__version__", "core", "simulators"] -from . import core, simulators try: from ._version import version as __version__ @@ -12,3 +11,5 @@ __version__ = get_version(root="../..", relative_to=__file__) except Exception: __version__ = "0.0.0+unknown" + +from . import core, simulators diff --git a/src/tuesday/core/__init__.py b/src/tuesday/core/__init__.py index 4a75c584..66750cb0 100644 --- a/src/tuesday/core/__init__.py +++ b/src/tuesday/core/__init__.py @@ -19,6 +19,7 @@ "plot_1d_power_spectrum_z", "plot_2d_power_spectrum", "plot_coeval_slice", + "plot_lightcone_slice", "plot_pdf", "plot_power_spectrum", "plot_redshift_slice", @@ -48,6 +49,7 @@ lc2slice_x, lc2slice_y, plot_coeval_slice, + plot_lightcone_slice, plot_pdf, plot_redshift_slice, ) diff --git a/src/tuesday/core/plotting/__init__.py b/src/tuesday/core/plotting/__init__.py index 9e12b291..a54fdb3c 100644 --- a/src/tuesday/core/plotting/__init__.py +++ b/src/tuesday/core/plotting/__init__.py @@ -5,9 +5,9 @@ "plot_1d_power_spectrum_z", "plot_2d_power_spectrum", "plot_coeval_slice", + "plot_lightcone_slice", "plot_pdf", "plot_power_spectrum", - "plot_redshift_slice", ] from .powerspectra import ( @@ -16,4 +16,4 @@ plot_2d_power_spectrum, plot_power_spectrum, ) -from .sliceplots import plot_coeval_slice, plot_pdf, plot_redshift_slice +from .sliceplots import plot_coeval_slice, plot_lightcone_slice, plot_pdf diff --git a/src/tuesday/core/plotting/sliceplots.py b/src/tuesday/core/plotting/sliceplots.py index f223026b..24d94c2f 100644 --- a/src/tuesday/core/plotting/sliceplots.py +++ b/src/tuesday/core/plotting/sliceplots.py @@ -5,10 +5,13 @@ import matplotlib.pyplot as plt import numpy as np from astropy import units as un +from deprecation import deprecated from matplotlib import colormaps, colors, rcParams from matplotlib.colors import LogNorm from scipy.ndimage import gaussian_filter +from tuesday import __version__ + from ..units import validate try: @@ -174,7 +177,7 @@ def slice_index(box: un.Quantity) -> un.Quantity: return slice_index -def plot_redshift_slice( +def plot_lightcone_slice( lightcone: un.Quantity, box_length: un.Quantity, redshift: np.ndarray | un.Quantity, @@ -198,6 +201,9 @@ def plot_redshift_slice( ) -> plt.Axes: """Plot a slice from a lightcone of shape (N_x, N_y, N_redshifts). + The plot will have redshift on the x-axis and (transverse) distance on the y-axis, + so it will show the cosmic evolution of the volume along the line of sight. + Parameters ---------- lightcone : un.Quantity @@ -236,8 +242,6 @@ def plot_redshift_slice( Whether to apply Gaussian smoothing to the lightcone data. If True, a default sigma of 1.0 will be used. If a float, it will be used as the sigma for the Gaussian filter. - - """ validate(box_length, "length") rcParams.update({"font.size": fontsize}) @@ -257,7 +261,7 @@ def plot_redshift_slice( if clabel is None: if lightcone.unit.physical_type == un.get_physical_type("temperature"): - clabel = "Brightness Temperature " + f" [{lightcone.unit:latex_inline}]" + clabel = f"Brightness Temperature [{lightcone.unit:latex_inline}]" elif lightcone.unit.is_equivalent(un.dimensionless_unscaled): clabel = "Density Contrast" else: @@ -289,6 +293,20 @@ def plot_redshift_slice( ) +@deprecated( + deprecated_in="2.3.2", + removed_in="3.0.0", + current_version=__version__, + details="Please use plot_lightcone_slice instead", +) +def plot_redshift_slice(*args, **kwargs): + """PLot a slice from a lightcone. + + Deprecated: use plot_lightcone_slice instead. + """ + return plot_lightcone_slice(*args, **kwargs) + + def plot_coeval_slice( coeval: un.Quantity, box_length: un.Quantity, diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py index b988bd34..b1951269 100644 --- a/tests/test_dataclasses.py +++ b/tests/test_dataclasses.py @@ -31,11 +31,9 @@ def ps(): def test_one_ps_per_obj(ps, ps2): - with pytest.raises(ValueError, match="The ps array must be 1D for a SphericalPS."): + with pytest.raises(ValueError, match="The ps array must be 1D for a SphericalPS"): SphericalPS(np.append(ps.ps[None, ...], ps.ps[None, ...], axis=0), k=ps.k) - with pytest.raises( - ValueError, match="The ps array must be 2D for a CylindricalPS." - ): + with pytest.raises(ValueError, match="The ps array must be 2D for a CylindricalPS"): CylindricalPS( np.append(ps2.ps[None, ...], ps2.ps[None, ...], axis=0), kperp=ps2.kperp, diff --git a/tests/test_lc_noise.py b/tests/test_lc_noise.py index 4f1a0d63..deb6e6b1 100644 --- a/tests/test_lc_noise.py +++ b/tests/test_lc_noise.py @@ -72,10 +72,7 @@ def test_thermal_noise_per_voxel(observation): observation, np.array([150.0, 120.0]) * un.MHz, boxlength, lc_shape ) with pytest.raises( - ValueError, - match="You cannot provide both beam_area " - "and antenna_effective_area." - " Proceding with beam_area.", + ValueError, match="You cannot provide both beam_area and antenna_effective_area" ): thermal_noise_per_voxel( observation, @@ -87,8 +84,7 @@ def test_thermal_noise_per_voxel(observation): ) with pytest.raises( ValueError, - match="Antenna effective area must either be a float or have the" - " same shape as freqs.", + match="Antenna effective area must either be a float or have the same shape", ): thermal_noise_per_voxel( observation, @@ -98,7 +94,7 @@ def test_thermal_noise_per_voxel(observation): antenna_effective_area=[517.7, 200.0] * un.m**2, ) with pytest.raises( - ValueError, match="Beam area must be a float or have the same shape as freqs." + ValueError, match="Beam area must be a float or have the same shape as freqs" ): thermal_noise_per_voxel( observation, diff --git a/tests/test_plotting_boxes.py b/tests/test_plotting_boxes.py index 8372f0f9..13f0f06e 100644 --- a/tests/test_plotting_boxes.py +++ b/tests/test_plotting_boxes.py @@ -3,6 +3,7 @@ import astropy.units as un import numpy as np import pytest +from deprecation import fail_if_not_removed from tuesday.core import ( coeval2slice_x, @@ -11,6 +12,7 @@ lc2slice_x, lc2slice_y, plot_coeval_slice, + plot_lightcone_slice, plot_pdf, plot_redshift_slice, ) @@ -82,7 +84,7 @@ def test_coeval_slice(test_coeval): def test_lightcone_slice(test_lc, test_redshifts): """Test the plot_lightcone_slice function.""" box_len = 300 * un.cm - ax = plot_redshift_slice( + ax = plot_lightcone_slice( test_lc.value * un.dimensionless_unscaled, box_len, test_redshifts, @@ -93,7 +95,7 @@ def test_lightcone_slice(test_lc, test_redshifts): assert ax.get_xlabel() == "Redshift" assert ax.get_title() == "tiny lightcone" - ax = plot_redshift_slice( + ax = plot_lightcone_slice( test_lc.value * un.mK**2, box_len, test_redshifts, @@ -105,14 +107,14 @@ def test_lightcone_slice(test_lc, test_redshifts): transform2slice=lc2slice_x(idx=5), ) - ax = plot_redshift_slice( + ax = plot_lightcone_slice( test_lc, box_len, test_redshifts, transform2slice=lc2slice_y(idx=5), smooth=True, ) - ax = plot_redshift_slice( + ax = plot_lightcone_slice( test_lc, box_len, test_redshifts, @@ -169,3 +171,16 @@ def test_plot_slice(test_coeval): np.linspace(0, box_len.value, test_coeval.shape[0]) * un.cm, np.linspace(0, box_len.value, test_coeval.shape[1]) * un.Mpc, ) + + +@fail_if_not_removed +def test_deprecated_plot_redshift_slice(test_lc, test_redshifts): + """Test the deprecated plot_redshift_slice function.""" + box_len = 300 * un.cm + plot_redshift_slice( + test_lc.value * un.dimensionless_unscaled, + box_len, + test_redshifts, + title="tiny lightcone", + transform2slice=lc2slice_y(idx=5), + ) diff --git a/tests/test_plotting_ps.py b/tests/test_plotting_ps.py index ea7695f5..42936e4e 100644 --- a/tests/test_plotting_ps.py +++ b/tests/test_plotting_ps.py @@ -87,9 +87,7 @@ def test_1d_ps_plot(ps1d: SphericalPS): with pytest.raises( ValueError, - match="power_spectrum must be a SphericalPS object or a list of " - "SphericalPS objects," - " got instead.", + match="power_spectrum must be a SphericalPS object or a list of SphericalPS", ): plot_1d_power_spectrum_z( [ps1d, np.ones((10, 10))],