# Source code for africanus.gridding.util

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np

[docs]def estimate_cell_size(u, v, wavelength, factor=3.0, ny=None, nx=None):
r"""
Estimate the cell size in arcseconds given
baseline u and v coordinates, as well
as the wavelengths, :math:\lambda.

The cell size is computed as:

.. math::

\Delta u = 1.0 / \left( 2 \times \text{ factor }
\times \max (\vert u \vert)
/ \min( \lambda) \right)

\Delta v = 1.0 / \left( 2 \times \text{ factor }
\times \max (\vert v \vert)
/ \min( \lambda) \right)

If ny and nx are provided the following checks are performed
and exceptions are raised on failure:

.. math::

\Delta u * \text{ ny } \leq \min (\lambda) / \min (\vert u \vert)

\Delta v * \text{ nx } \leq \min (\lambda) / \min (\vert v \vert)

Parameters
----------
u : :class:numpy.ndarray or float
Maximum u coordinate in metres.
v : :class:numpy.ndarray or float
Maximum v coordinate in metres.
wavelength : :class:numpy.ndarray or float
Wavelengths, in metres.
factor : float, optional
Scaling factor
ny : int, optional
Grid y dimension
nx : int, optional
Grid x dimension

Raises
------
ValueError
If the cell size criteria are not matched.

Returns
-------
:class:numpy.ndarray
Cell size of u and v in arcseconds with shape :code:(2,)
"""
if isinstance(u, np.ndarray):
abs_u = np.abs(u)
umax = abs_u.max()
umin = abs_u.min()
elif isinstance(u, float):
umax = umin = abs(u)
else:
raise TypeError("Invalid u type %s" % type(u))

if isinstance(v, np.ndarray):
abs_v = np.abs(v)
vmax = abs_v.max()
vmin = abs_v.min()
elif isinstance(v, float):
vmax = vmin = abs(v)
else:
raise TypeError("Invalid v type %s" % type(v))

if isinstance(wavelength, np.ndarray):
wave_min = wavelength.min()
elif isinstance(wavelength, float):
wave_min = wavelength
else:
raise TypeError("Invalid wavelength type %s" % type(v))

umax /= wave_min
vmax /= wave_min
umin /= wave_min
vmin /= wave_min

u_cell_size = 1.0 / (2.0 * factor * umax)
v_cell_size = 1.0 / (2.0 * factor * vmax)

if ny is not None and u_cell_size*ny < (1.0 / umin):
raise ValueError("v_cell_size*ny [%f] < (1.0 / umin) [%f]" %
(u_cell_size*ny, 1.0 / umin))

if nx is not None and v_cell_size*nx < (1.0 / vmin):
raise ValueError("v_cell_size*nx [%f] < (1.0 / vmin) [%f]" %
(v_cell_size*nx, 1.0 / vmin))