Source code for cygrid.mock

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np


__all__ = ['produce_mock_data']


[docs] def produce_mock_data( mapcenter, mapsize, beamsize_fwhm, num_samples, num_sources ): ''' Produce mock raw data (including coordinate pairs) for testing. The raw data mimics a continuum observation (i.e., one flux density value per position) containing only Gaussian noise and some point sources. Parameters ---------- mapcenter : tuple of floats Center coordinates, `(lon, lat)` of the generated (rectangular) map [deg]. mapsize : tuple of floats Size of map, `(width, height)` of the generated map [deg]. beamsize_fwhm : float FWHM beam size [deg]. The artificial point sources, which are sampled, will be convolved with this. num_samples : int Number of samples to produce. Note that this must be large enough to ensure full sampling of the map (otherwise artifacts will appear, which are caused by so-called aliasing). num_sources : int Number of artificial point sources to be placed into the map. Returns ------- lons : `~numpy.array` of float64 [1D] Longitude coordinates for each sample. lats : `~numpy.array` of float64 [1D] Latitude coordinates for each sample. signal : `~numpy.array` of float64 [1D] The artifical raw data signal for each position. Notes ----- As in real astronomical measurements, the point sources are convolved with the instrument's response function (PSF), or telescope beam. The longitude map size is scaled with :math:`\\cos b`, where :math:`b` is the latitude. This is to ensure that the true-angular size roughly matches the given map width. ''' lon_scale = np.cos(np.radians(mapcenter[1])) map_l, map_r = ( mapcenter[0] - 1.1 * mapsize[0] / 2. / lon_scale, mapcenter[0] + 1.1 * mapsize[0] / 2. / lon_scale ) map_b, map_t = ( mapcenter[1] - 1.1 * mapsize[1] / 2., mapcenter[1] + 1.1 * mapsize[1] / 2., ) # coordinates are drawn from a uniform distribution lons = np.random.uniform(map_l, map_r, num_samples).astype(np.float64) lats = np.random.uniform(map_b, map_t, num_samples).astype(np.float64) # add Gaussian noise signal = np.random.normal(0., 1., len(lons)) beamsize_sigma = beamsize_fwhm / np.sqrt(8 * np.log(2)) # put in artifical point source, with random amplitudes # we'll assume a Gaussian-shaped PSF def gauss2d(x, y, x0, y0, A, s): return A * np.exp(-((x - x0) ** 2 + (y - y0) ** 2) / 2. / s ** 2) for _ in range(num_sources): sou_x = np.random.uniform(map_l, map_r, 1).astype(np.float64) sou_y = np.random.uniform(map_b, map_t, 1).astype(np.float64) A = np.random.uniform(0, 10, 1) signal += gauss2d(lons, lats, sou_x, sou_y, A, beamsize_sigma) return lons, lats, signal