-
Notifications
You must be signed in to change notification settings - Fork 11
WIP: PrimaryBeam correction #103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
14d0c8e
b0e8acc
8223316
5677547
38edec6
34111dd
cc66a59
0beb730
3ef5c32
f074ba4
f2a4958
0bff7f5
e4a38a3
e710838
db59a7c
60e869a
f61fd4d
4c93b82
ba500c8
a35bbab
b1f7988
4f2dc66
38a50cd
1d2623d
1297ade
2e54406
5a05c9b
f8bfcf5
3518f82
216e633
575e9c2
e5313de
8254151
161ed00
fb2dd04
34d1934
7eddf26
29334bd
6e00ea1
3e7226f
795a2a8
34e7dc2
2455da3
c513f1d
8875cd6
318fea6
0a7648d
66f3825
c3c20b3
f3b7ee6
c70103c
0d3f247
a63adb9
b431530
aa06b99
27c9f43
62ea137
e64138c
aa11463
0effac0
1784ff1
7b848f0
ebe31d8
80f0e43
85f01b3
5947598
17933f7
0f411a9
9460d76
1396ce3
d90977d
be33fb1
12428d1
205691e
8d3dd3c
0d597d4
57d0b16
300e736
a506c7f
17db0a6
340ccf6
0d8e97f
39b42e0
901d439
30ad09b
b217642
7c9667f
855e8c7
6636d52
b1d904a
b6d9b24
a32f97e
90319c1
8bee203
4bd668a
72535e4
5055ab2
354bf4c
5aafb7d
c42096c
740d766
45e9e35
21e7606
fdbb675
87e4775
3b9afac
cbb70a1
de1d0f3
0fdfa2d
d4d4ce2
761ea22
61661c5
1324b33
56fe908
a93fe92
d902788
4996ada
8ea668e
d0a005d
91827c3
30a161a
d140df0
812465f
1e2ae17
fc30cb3
efdb9e4
8a0d6af
eb12a5c
82f3386
fb84d3e
6b1c8ec
2a40109
8837f77
f5328e0
2b60981
b5f3436
d1d7152
312bb6d
da584d1
5ded8a3
c666ea7
ab4083e
2913d27
5dc942b
0ec9c57
a4dce28
7c41bb4
a1abde7
78dd758
7bcc503
512ca46
7f36977
7bd4a78
63df35f
3a718ae
86bbf66
bd3c351
e55fd2c
7c3d73d
f5dbfa6
9b0be2d
e6be9e6
d8c9450
257d9e2
f99599e
337c297
19fb53e
1730632
fc8f90e
b7b7c4c
ad7a847
7fc9b15
45f0603
4d58e2d
8032696
2fd2c10
eecee5a
fed638f
8a13621
e3287a0
dd9fded
1a2b87c
5331457
3d91ad7
0cd0042
274bb69
509f323
1a1b042
c8a8dac
fad39a8
801cacc
024db57
c80fd3f
70dabe6
6ef516c
ae89ee0
8f2bcf8
c4a7cd0
aab7365
b710ff4
7a8b87f
f57fee8
4dd7cb5
192c859
21f4818
ccf4d1e
ca9e75c
207bbb4
1a11f95
9f0fa47
873af84
c79e169
c09306d
409533a
2fc1331
018062b
ece5402
f30b29e
275e13f
4ad59e2
ec183db
7931fdc
62c423a
886bad2
62257a8
cf3633e
87c066f
09c01b8
4d38055
ce720ff
08e4377
b74b497
d328e81
c1290f2
3913596
b07162e
c700004
3d1de04
5551ff6
ad3653a
d3852b2
2006878
5eb95ee
02651fb
b7d9a78
5a7d7f0
aa8eb55
503acd3
cf042b8
45639dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| r"""The ``images`` module provides the core functionality of MPoL via :class:`mpol.images.ImageCube`.""" | ||
|
|
||
| import numpy as np | ||
| from scipy.special import j1 | ||
| import torch | ||
| import torch.fft # to avoid conflicts with old torch.fft *function* | ||
| from torch import nn | ||
|
|
@@ -279,6 +280,120 @@ def to_FITS(self, fname="cube.fits", overwrite=False, header_kwargs=None): | |
|
|
||
| hdul.close() | ||
|
|
||
| class PBCorrectedCube(nn.Module): | ||
| r""" | ||
| A ImageCube that has been corrected for the expected primary beam. Currently only implemented for ALMA. | ||
|
|
||
| Args: | ||
| cell_size (float): the width of a pixel [arcseconds] | ||
| npix (int): the number of pixels per image side | ||
| coords (GridCoords): an object already instantiated from the GridCoords class. If providing this, cannot provide ``cell_size`` or ``npix``. | ||
| nchan (int): the number of channels in the image | ||
| """ | ||
| def __init__( | ||
| self, | ||
| cell_size=None, | ||
| npix=None, | ||
| coords=None, | ||
| chan_freqs=None, | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpicky, but I would say |
||
| telescope="ALMA_12" | ||
| ): | ||
| nchan = len(np.at_least_1d(chan_freqs)) | ||
| super().__init__() | ||
| _setup_coords(self, cell_size, npix, coords, nchan) | ||
|
|
||
| self.telescope_to_radius = {"ALMA_12": 6.} # in meters | ||
| self.telescope_to_blocked_radius = {"ALMA_12": 0.375} | ||
|
|
||
| assert (telescope in self.telescope_to_radius) and (telescope in self.telescope_to_blocked_radius) | ||
|
||
|
|
||
| self.pb_mask = self.obscured_airy_disk(chan_freqs, telescope) | ||
|
||
|
|
||
|
|
||
| def forward(self, cube): | ||
| r"""Args: | ||
| cube (torch.double tensor, of shape ``(nchan, npix, npix)``): a prepacked image cube, for example, from ImageCube.forward() | ||
|
|
||
| Returns: | ||
| (torch.complex tensor, of shape ``(nchan, npix, npix)``): the FFT of the image cube, in packed format. | ||
| """ | ||
| return self.pb_mask * cube | ||
|
|
||
| def obscured_airy_disk(self, telescope): | ||
| r""" | ||
| Generates airy disk primary beam correction mask assuming some is obscured | ||
| by secondary reflector. | ||
| """ | ||
|
|
||
| R = telescope_to_radius[telescope] | ||
| R_obs = telescope_to_blocked_radius[telescope] | ||
|
|
||
| r_coords = np.sqrt(self.packed_x_centers_2D**2 + self.packed_y_centers_2D**2) # units of arcsec | ||
| r_coords_rads = r_coords * np.pi/648000. # radians | ||
|
||
| wl = 2.998e8 / self.chan_freqs[0] # TODO: handle multiple channels | ||
| x = np.pi * R * r_coords_rads / wl | ||
|
|
||
| eps = R_obs / R | ||
| j1_x = scipy.special.j1(x) | ||
| j1_epsx = scipy.special.j1(eps * x) | ||
| mask = 4. * (j1_x / x - eps * j1_epsx / x)**2 / (1. - eps**2)**2 | ||
|
|
||
| return mask | ||
|
|
||
| @property | ||
| def sky_cube(self): | ||
| """ | ||
| The image cube arranged as it would appear on the sky. | ||
|
|
||
| Returns: | ||
| torch.double : 3D image cube of shape ``(nchan, npix, npix)`` | ||
|
|
||
| """ | ||
| return utils.packed_cube_to_sky_cube(self.cube) | ||
|
|
||
| def to_FITS(self, fname="cube.fits", overwrite=False, header_kwargs=None): | ||
| """ | ||
| Export the image cube to a FITS file. | ||
|
|
||
| Args: | ||
| fname (str): the name of the FITS file to export to. | ||
| overwrite (bool): if the file already exists, overwrite? | ||
| header_kwargs (dict): Extra keyword arguments to write to the FITS header. | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
|
|
||
| try: | ||
| from astropy import wcs | ||
| from astropy.io import fits | ||
| except ImportError: | ||
| print( | ||
| "Please install the astropy package to use FITS export functionality." | ||
| ) | ||
|
|
||
| w = wcs.WCS(naxis=2) | ||
|
|
||
| w.wcs.crpix = np.array([1, 1]) | ||
| w.wcs.cdelt = ( | ||
| np.array([self.coords.cell_size, self.coords.cell_size]) / 3600 | ||
| ) # decimal degrees | ||
| w.wcs.ctype = ["RA---TAN", "DEC--TAN"] | ||
|
|
||
| header = w.to_header() | ||
|
|
||
| # add in the kwargs to the header | ||
| if header_kwargs is not None: | ||
| for k, v in header_kwargs.items(): | ||
| header[k] = v | ||
|
|
||
| hdu = fits.PrimaryHDU(self.sky_cube.detach().cpu().numpy(), header=header) | ||
|
|
||
| hdul = fits.HDUList([hdu]) | ||
| hdul.writeto(fname, overwrite=overwrite) | ||
|
|
||
| hdul.close() | ||
|
|
||
|
|
||
| class FourierCube(nn.Module): | ||
| r""" | ||
|
|
@@ -292,7 +407,7 @@ class FourierCube(nn.Module): | |
|
|
||
| def __init__(self, cell_size=None, npix=None, coords=None): | ||
|
|
||
| super().__init__() | ||
| super().__init__(cell_size) | ||
|
||
|
|
||
| # we don't want to bother with the nchan argument here, so | ||
| # we don't use the convenience method _setup_coords | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,6 +50,11 @@ def __init__( | |
| self.icube = images.ImageCube( | ||
| coords=self.coords, nchan=self.nchan, passthrough=True | ||
| ) | ||
|
|
||
| self.pbcube = images.PBCorrectedCube( | ||
|
||
| coords = self.coords, nchan=self.nchan, telescope="ALMA_12" | ||
| ) | ||
|
|
||
| self.fcube = images.FourierCube(coords=self.coords) | ||
|
|
||
| def forward(self): | ||
|
|
@@ -61,5 +66,6 @@ def forward(self): | |
| x = self.bcube.forward() | ||
| x = self.conv_layer(x) | ||
| x = self.icube.forward(x) | ||
| x = self.pbcube.forward(x) | ||
| vis = self.fcube.forward(x) | ||
| return vis | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned in the issue, I think you can be agnostic about which array this is, and split the corrections into two classes, one for a uniform illuminated dish, and the other with a central blockage.