Simulation and sensitivity commands#

These commands separate the calculation into two stages. First, simu_uv simulates and grids the UV coverage of one observing track. The resulting HDF5 file can then be reused to calculate an image-domain noise realization, power-spectrum noise, or sensitivity for a chosen total accumulated integration time.

simu_uv#

Simulate gridded UV coverage for an instrument and redshift:

$ pstool simu_uv nenufar 8.5 \
    --total_time 10 --int_time 60 \
    --bandwidth 10 --df 195.3 \
    --out_filename coverage

The command accepts a single redshift or an increasing range such as 8-10. Available instrument names are shown by pstool simu_uv --help and include configurations for SKA-Low, NenuFAR, LOFAR, AARTFAAC, MWA, HERA, and DEx.

--dec_deg sets a tracked pointing declination; use drift for drift mode. --fov accepts a size in degrees, pb_fwhm, or pb_fwhm_tapered. The tapered option uses a field three times the primary beam FWHM with a circular Blackman–Harris window. Other options control UV limits, channelization, observation duration, time resolution, and image resolution.

The output basename includes the instrument, redshift, and observing time. The command writes the simulated coverage to HDF5 and a PDF UV-coverage plot. The HDF5 file is the input to the three noise commands below.

Python API. Load the HDF5 output with ps_eor.obssimu.SimuGridded.load(). It provides the simulated weights, SEFD, noise standard deviation, and a configured power-spectrum estimator; see Observation simulation and thermal noise and the simulation API.

simu_noise_img#

Generate one image-domain thermal-noise realization from simulated UV coverage:

$ pstool simu_noise_img coverage_nenufar_z8.5_10h.h5 100 \
    --min_weight 10 --out_filename noise

TOTAL_TIME_HOUR is the total accumulated observing time represented by the noise level, which can differ from the duration used to generate one night’s UV track. The command writes a frequency-dependent FITS image cube and reports its RMS. It is not implemented for redundant-array coverage.

Python API. For continued processing in memory, load the original coverage with ps_eor.obssimu.SimuGridded.load(), generate the noise through its weights, and call ps_eor.datacube.CartDataCube.image() to obtain a CartImageCube. The programmatic path is shown in Observation simulation and thermal noise.

simu_noise_ps#

Calculate expected spatial, cylindrical, and spherical thermal-noise power and their statistical sensitivity:

$ pstool simu_noise_ps coverage_nenufar_z8.5_10h.h5 100 \
    --kmax 0.5 --nks 8 \
    --filter_kpar_min 0.05 \
    --out_filename sensitivity

The command uses the telescope’s frequency-dependent SEFD unless --sefd supplies a fixed value. --filter_kpar_min and --filter_wedge_theta exclude modes during spherical averaging. --n_incoherent_avg reduces the statistical error to represent independent incoherent averages. --nks is the number of bin edges, so --nks 8 produces seven spherical k bins.

The filtering options estimate the sensitivity of a foreground-avoidance selection. They discard the selected Fourier modes from the spherical average; they do not simulate foreground subtraction.

For each dimensionality, a text file and PDF are written. The plotted noise curve is expected thermal-noise power; the spherical plot additionally shows twice the .err value as the two-sigma sensitivity.

Python API. Reload the text products with ps_eor.pspec.SpatialPowerSpectra.load(), ps_eor.pspec.CylindricalPowerSpectra.load(), and ps_eor.pspec.SphericalPowerSpectra.load_from_txt(). To reproduce or extend the calculation directly, use ps_eor.obssimu.SimuGridded.get_noise_std_cube() and get_ps_gen().

Drift-scan accumulation#

For a drift-scan instrument, the UV-coverage file should represent one coherent LST block. Repeated observations of that block on different nights sample the same sky, so their combined duration is supplied as TOTAL_TIME_HOUR to simu_noise_ps. Independent LST blocks sample different sky regions and are combined at the power-spectrum level with --n_incoherent_avg.

For example, simulate a three-minute HERA LST block:

$ pstool simu_uv hera_320 7 \
    --total_time 0.05 --int_time 30 \
    --out_filename coverage

One hundred observations of the same block provide five hours of coherent integration. The following command also represents an incoherent average over 100 independent LST blocks:

$ pstool simu_noise_ps coverage_hera_320_z7.0_0.05h.h5 5 \
    --nks 8 --kmax 1.2 \
    --n_incoherent_avg 100

--n_incoherent_avg leaves the expected noise power unchanged and reduces its statistical error by the square root of the number of independent averages.

simu_noise_ps_zrange#

Follow thermal-noise power and sensitivity at one spherical wavenumber across the redshift span stored in a coverage file:

$ pstool simu_noise_ps_zrange coverage_wideband.h5 100 0.1 \
    --bandwidth 10 --delta_z 0.5 --dk_over_k 0.4 \
    --out_filename sensitivity

The requested K is converted to a bin using --dk_over_k. Each redshift uses a sub-band of width --bandwidth. Wedge, minimum k_parallel, minimum UV weight, and incoherent-average options have the same meaning as for simu_noise_ps. --smooth applies smoothing to the final redshift curves.

The output text file contains redshift, k-bin limits, mean k, thermal-noise power, and one-sigma error. A PDF compares the noise power with the two-sigma sensitivity.

Python API. Load the wide-band coverage with ps_eor.obssimu.SimuGridded.load(), select each sub-band with get_slice(), and calculate its noise and power spectra as described in Observation simulation and thermal noise.