Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# -- Project information -----------------------------------------------------
from pkg_resources import DistributionNotFound, get_distribution

Expand Down
7 changes: 7 additions & 0 deletions src/mpol/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
import importlib.metadata

try:
__version__ = importlib.metadata.version("MPoL")
except importlib.metadata.PackageNotFoundError:
__version__ = "unknown"

zenodo_record = 10064221
4 changes: 2 additions & 2 deletions src/mpol/coordinates.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class GridCoords:
length-4 list of (left, right, bottom, top) expected by routines
like ``matplotlib.pyplot.imshow`` in the ``extent`` parameter assuming
``origin='lower'``. Units of [:math:`\lambda`]
vis_ext_Mlam : list
vis_ext_Mlam : list
like vis_ext, but in units of [:math:`\mathrm{M}\lambda`].
"""

Expand Down Expand Up @@ -273,7 +273,7 @@ def ground_q_centers_2D(self) -> npt.NDArray[np.floating[Any]]:
@cached_property
def sky_phi_centers_2D(self) -> npt.NDArray[np.floating[Any]]:
# https://en.wikipedia.org/wiki/Atan2
return np.arctan2( # type: ignore
return np.arctan2( # type: ignore
self.ground_v_centers_2D, self.ground_u_centers_2D
) # (pi, pi]

Expand Down
6 changes: 3 additions & 3 deletions src/mpol/crossval.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
# Number of k-folds to use in cross-validation
# split_method : str, default='dartboard'
# Method to split full dataset into train/test subsets
# dartboard_q_edges, dartboard_phi_edges : list of float, default=None,
# dartboard_q_edges, dartboard_phi_edges : list of float, default=None,
# unit=[klambda]
# Radial and azimuthal bin edges of the cells used to split the dataset
# if `split_method`==`dartboard` (see `datasets.Dartboard`)
Expand Down Expand Up @@ -510,7 +510,7 @@ def __init__(
self.cell_list = self.dartboard.get_nonzero_cell_indices(qs, phis)

# indices of cells in the smallest q bin that also have data
small_q_idx = [i for i, l in enumerate(self.cell_list) if l[0] == 0] #type: ignore
small_q_idx = [i for i, l in enumerate(self.cell_list) if l[0] == 0] # type: ignore
# cells in the smallest q bin
self.small_q = self.cell_list[: len(small_q_idx)]

Expand Down Expand Up @@ -554,7 +554,7 @@ def from_dartboard_properties(
seed (int): (optional) numpy random seed to use for the permutation,
for reproducibility
verbose (bool): whether to print notification messages
"""
"""
dartboard = Dartboard(gridded_dataset.coords, q_edges, phi_edges)
return cls(gridded_dataset, k, dartboard, seed, verbose)

Expand Down
14 changes: 8 additions & 6 deletions src/mpol/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class GriddedDataset(torch.nn.Module):
If providing this, cannot provide ``cell_size`` or ``npix``.
vis_gridded : :class:`torch.Tensor` of :class:`torch.complex128`
the gridded visibility data stored in a "packed" format (pre-shifted for fft)
weight_gridded : :class:`torch.Tensor`
weight_gridded : :class:`torch.Tensor`
the weights corresponding to the gridded visibility data,
also in a packed format
mask : :class:`torch.Tensor` of :class:`torch.bool`
Expand Down Expand Up @@ -117,9 +117,9 @@ def forward(self, modelVisibilityCube: torch.Tensor) -> torch.Tensor:
across cube dimensions.
"""

assert (
modelVisibilityCube.size()[0] == self.mask.size()[0]
), "vis and dataset mask do not have the same number of channels."
assert modelVisibilityCube.size()[0] == self.mask.size()[0], (
"vis and dataset mask do not have the same number of channels."
)

# As of Pytorch 1.7.0, complex numbers are partially supported.
# However, masked_select does not yet work (with gradients)
Expand Down Expand Up @@ -226,8 +226,10 @@ def get_polar_histogram(

histogram: NDArray
# make a polar histogram
histogram, *_ = np.histogram2d( # type:ignore
qs, phis, bins=[self.q_edges.tolist(), self.phi_edges.tolist()] # type:ignore
histogram, *_ = np.histogram2d( # type:ignore
qs,
phis,
bins=[self.q_edges.tolist(), self.phi_edges.tolist()], # type:ignore
)

return histogram
Expand Down
15 changes: 5 additions & 10 deletions src/mpol/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
from __future__ import annotations


class CellSizeError(Exception):
...
class CellSizeError(Exception): ...


class WrongDimensionError(Exception):
...
class WrongDimensionError(Exception): ...


class DataError(Exception):
...
class DataError(Exception): ...


class DimensionMismatchError(Exception):
...
class DimensionMismatchError(Exception): ...


class ThresholdExceededError(Exception):
...
class ThresholdExceededError(Exception): ...
9 changes: 4 additions & 5 deletions src/mpol/fourier.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,14 @@ def forward(

Parameters
----------
packed_cube : :class:`torch.Tensor`
packed_cube : :class:`torch.Tensor`
shape ``(nchan, npix, npix)``). The cube
should be a "prepacked" image cube, for example,
from :meth:`mpol.images.ImageCube.forward`
uu : :class:`torch.Tensor`
uu : :class:`torch.Tensor`
2D array of the u (East-West) spatial frequency coordinate
[:math:`\lambda`] of shape ``(nchan, npix)``
vv : :class:`torch.Tensor`
vv : :class:`torch.Tensor`
2D array of the v (North-South) spatial frequency coordinate
[:math:`\lambda`] (must be the same shape as uu)
sparse_matrices : bool
Expand Down Expand Up @@ -506,7 +506,7 @@ def forward(self, packed_cube):
``uu`` and ``vv`` points.

Args:
packed_cube : :class:`torch.Tensor`
packed_cube : :class:`torch.Tensor`
shape ``(nchan, npix, npix)``). The cube
should be a "prepacked" image cube, for example,
from :meth:`mpol.images.ImageCube.forward`
Expand All @@ -530,7 +530,6 @@ def forward(self, packed_cube):
# convert the cube to a complex type, since this is required by TorchKbNufft
complexed = shifted + 0j


# Consider how the similarity of the spatial frequency samples should be
# treated. We already took care of this on the k_traj side, since we set
# the shapes. But this also needs to be taken care of on the image side.
Expand Down
3 changes: 1 addition & 2 deletions src/mpol/geometry.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""The geometry package provides routines for projecting and de-projecting sky images.
"""
"""The geometry package provides routines for projecting and de-projecting sky images."""

import numpy as np
import torch
Expand Down
42 changes: 21 additions & 21 deletions src/mpol/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ def __init__(
self.base_cube = nn.Parameter(base_cube, requires_grad=True)

if pixel_mapping is None:
self.pixel_mapping: Callable[
[torch.Tensor], torch.Tensor
] = torch.nn.Softplus()
self.pixel_mapping: Callable[[torch.Tensor], torch.Tensor] = (
torch.nn.Softplus()
)
else:
self.pixel_mapping = pixel_mapping

Expand Down Expand Up @@ -193,10 +193,10 @@ def forward(self, cube: torch.Tensor) -> torch.Tensor:

class GaussConvImage(nn.Module):
r"""
This convolutional layer will convolve the input cube with a 2D Gaussian kernel.
This convolutional layer will convolve the input cube with a 2D Gaussian kernel.
The filter is the same for all channels in the input cube.
Because the operation is carried out in the image domain, note that it may become
computationally prohibitive for large kernel sizes. In that case,
computationally prohibitive for large kernel sizes. In that case,
:class:`mpol.images.GaussConvFourier` may be preferred.

Parameters
Expand Down Expand Up @@ -329,6 +329,7 @@ def forward(self, sky_cube: torch.Tensor) -> torch.Tensor:
convolved_sky = self.m(sky_cube)
return convolved_sky


class GaussConvFourier(nn.Module):
r"""
This layer will convolve the input cube with a (potentially non-circular) Gaussian
Expand All @@ -349,19 +350,18 @@ class GaussConvFourier(nn.Module):
"""

def __init__(
self,
coords: GridCoords,
FWHM_maj: float,
FWHM_min: float,
Omega: float = 0) -> None:
self, coords: GridCoords, FWHM_maj: float, FWHM_min: float, Omega: float = 0
) -> None:
super().__init__()

self.coords = coords
self.FWHM_maj = FWHM_maj
self.FWHM_min = FWHM_min
self.FWHM_min = FWHM_min
self.Omega = Omega

taper_2D = uv_gaussian_taper(self.coords, self.FWHM_maj, self.FWHM_min, self.Omega)
taper_2D = uv_gaussian_taper(
self.coords, self.FWHM_maj, self.FWHM_min, self.Omega
)

# store taper to register so it transfers to GPU
self.register_buffer("taper_2D", torch.tensor(taper_2D, dtype=torch.float32))
Expand All @@ -382,10 +382,10 @@ def forward(self, packed_cube, thresh=1e-6):
The convolved cube in packed format.
"""
nchan, npix_m, npix_l = packed_cube.size()
assert (
(npix_m == self.coords.npix) and (npix_l == self.coords.npix)
), "packed_cube {:} does not have the same pixel dimensions as indicated by coords {:}".format(
packed_cube.size(), self.coords.npix
assert (npix_m == self.coords.npix) and (npix_l == self.coords.npix), (
"packed_cube {:} does not have the same pixel dimensions as indicated by coords {:}".format(
packed_cube.size(), self.coords.npix
)
)

# in FFT packed format
Expand All @@ -400,10 +400,10 @@ def forward(self, packed_cube, thresh=1e-6):
convolved_packed_cube = torch.fft.ifftn(tapered_vis, dim=(1, 2))

# assert imaginaries are effectively zero, otherwise something went wrong
assert (
torch.max(convolved_packed_cube.imag) < thresh
), "Round-tripped image contains max imaginary value {:} > {:} threshold, something may be amiss.".format(
torch.max(convolved_packed_cube.imag), thresh
assert torch.max(convolved_packed_cube.imag) < thresh, (
"Round-tripped image contains max imaginary value {:} > {:} threshold, something may be amiss.".format(
torch.max(convolved_packed_cube.imag), thresh
)
)

r_cube: torch.Tensor = convolved_packed_cube.real
Expand Down Expand Up @@ -580,4 +580,4 @@ def uv_gaussian_taper(

# a flux-conserving taper must have an amplitude of 1 at the origin.

return taper_2D
return taper_2D
9 changes: 3 additions & 6 deletions src/mpol/input_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@ def __init__(self, filename, channel=0):
self._fits_file = filename
self._channel = channel


def get_extent(self, header):
"""Get extent (in RA and Dec, units of [arcsec]) of image"""

# get the coordinate labels
nx = header["NAXIS1"]
ny = header["NAXIS2"]

assert (
nx % 2 == 0 and ny % 2 == 0
), f"Image dimensions x {nx} and y {ny} must be even."
assert nx % 2 == 0 and ny % 2 == 0, (
f"Image dimensions x {nx} and y {ny} must be even."
)

# RA coordinates
CDELT1 = 3600 * header["CDELT1"] # arcsec (converted from decimal deg)
Expand All @@ -53,7 +52,6 @@ def get_extent(self, header):

return RA, DEC, ext


def get_beam(self, hdu_list, header):
"""Get the major and minor widths [arcsec], and position angle, of a
clean beam"""
Expand All @@ -72,7 +70,6 @@ def get_beam(self, hdu_list, header):

return BMAJ, BMIN, BPA


def get_image(self, beam=True):
"""Load a .fits image and return as a numpy array. Also return image
extent and optionally (`beam`) the clean beam dimensions"""
Expand Down
Loading
Loading