Skip to content
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

Deconvolving ringmap #122

Merged
merged 4 commits into from
Apr 20, 2021
Merged

Deconvolving ringmap #122

merged 4 commits into from
Apr 20, 2021

Conversation

jrs65
Copy link
Contributor

@jrs65 jrs65 commented Feb 3, 2021

No description provided.

@lgtm-com
Copy link

lgtm-com bot commented Feb 3, 2021

This pull request introduces 1 alert and fixes 1 when merging 47d5bd1 into 0c4b397 - view on LGTM.com

new alerts:

  • 1 for Unused local variable

fixed alerts:

  • 1 for Unnecessary pass

@lgtm-com
Copy link

lgtm-com bot commented Feb 3, 2021

This pull request introduces 1 alert and fixes 1 when merging 839bbf1 into 0c4b397 - view on LGTM.com

new alerts:

  • 1 for Unused local variable

fixed alerts:

  • 1 for Unnecessary pass

@wulfda02
Copy link

Currently, you have the "natural" EW weights as [4,3,2,1], but I think it should be [2,3,2,1]. The 0-cylinder separation baselines don't include any independent negative v baselines, unlike the non-zero cylinder separations (thus reducing their weight by half). Right?

else:  # self.weight_ew == "natural"
            weight_ew = n_ew - np.arange(n_ew)

@wulfda02
Copy link

Also, when forming the wiener filter, you are summing over the cylinder axis, as well as the +/-m axis in the denominator

C_inv = self.inv_SN + (mB.conj() * weight_ew[:, np.newaxis] * mB).sum(
                    axis=(1, -2)
                )

But, shouldn't we keep positive and negative m separate until after filtering? I.e. only sum over axis=-2

@jrs65
Copy link
Contributor Author

jrs65 commented Feb 18, 2021

Currently, you have the "natural" EW weights as [4,3,2,1], but I think it should be [2,3,2,1]. The 0-cylinder separation baselines don't include any independent negative v baselines, unlike the non-zero cylinder separations (thus reducing their weight by half). Right?

else:  # self.weight_ew == "natural"
            weight_ew = n_ew - np.arange(n_ew)

This is a good question. I am pretty sure it's correct, but it's not trivial to come up with a concrete explanation as to why.

Here are a few different stabs at it:

  • With reference to how the standard ringmap maker works, the non-zero positive cylinder separations get implicitly conjugated into the negative separations and so by your argument you need to halve the weighting of all of them. This is relevant for the deconvolved ringmap maker because the standard ringmap maker is essentially the limit as you take the primary beam width to zero.
  • Second, as you point out there aren't independent negative baselines, so in some sense you should get half the weighting, but because of that same property there zero cylinder separation beams are purely real and thus have no noise in an imaginary part, so they have half the variance (i.e. twice the weight). These basically cancel out. This is one of the subtleties of interferometry, for very short baselines the noise properties are very different for real and imaginary parts. Interestingly this slightly odd effect disappears when using m-modes (in the general sense, I'm not sure about this specific hybrid case atm).

@jrs65
Copy link
Contributor Author

jrs65 commented Feb 18, 2021

Also, when forming the wiener filter, you are summing over the cylinder axis, as well as the +/-m axis in the denominator

C_inv = self.inv_SN + (mB.conj() * weight_ew[:, np.newaxis] * mB).sum(
                    axis=(1, -2)
                )

But, shouldn't we keep positive and negative m separate until after filtering? I.e. only sum over axis=-2

In order to guarantee the output sky is real, you need to treat the positive/negative m's as separate measurements of the same underlying mode and only infer the m >= 0 modes (as the negative ones on the sky are simple conjugates). This is done in the m-mode papers, although I have a similar derivation of it for the hybrid case that I can tidy up. Ultimately it means that the +/- modes are independent measurements at a similar level to the different cylinders and thus you need to sum over both in the filter.

Ultimately I think the fact that the +/- modes are mostly disjoint (coming from above/below the NCP), means that this doesn't really matter a huge amount in the practical output for CHIME. However, any instrument that has an EW baseline length > 0, but < aperture width (i.e. a responses that covers both +/-m in some asymmetric manner) would need to account for this properly to get the right S/N weighting. CHIME gets away with it because either your baseline has + or - m response at a particular declination (but not both), or it is the 0-cyl separation in which case the response is symmetric for +/- m and they should get weighted equally.

@jrs65
Copy link
Contributor Author

jrs65 commented Feb 19, 2021

I'm having doubts about the relative cylinder weighting point. I think I'm going to need to write it all out to be sure. I'll circulate it when I've got something written up.

@lgtm-com
Copy link

lgtm-com bot commented Mar 15, 2021

This pull request fixes 1 alert when merging 8c42861 into 0c4b397 - view on LGTM.com

fixed alerts:

  • 1 for Unnecessary pass

@ssiegelx
Copy link
Contributor

I'm finding that the maps generated with this task are scaled down by a factor of 4 relative to maps created with the standard ringmap maker. Also the flux of point sources is off by a factor of four from their expected value.

This is also true of the deconvolving map maker task that I wrote that uses an external beam model.

example_normalization_problem_3c295.pdf

This plot shows an RA slice through the map at the (RA, Dec) of 3C 295. I'm showing the standard ring map maker in blue (i.e., using the BeamformEW task on the same HybridVis container), this task in red, and my map maker in green. The expected flux of the source is indicated by the black dashed line.

@wulfda02 Have you encountered this?

@wulfda02
Copy link

As I mentioned on the stacking call, I think this can be explained by the dirty beam amplitude after going through the wiener filter. It sounds like there's still some uncertainty as to why this amplitude isn't 1, but in my work I find that re-normalizing by this amplitude produces the correct flux for point sources.

@ssiegelx ssiegelx mentioned this pull request Mar 23, 2021
@ssiegelx
Copy link
Contributor

See PR #126 for an extension to this that allows for an external beam model.

@jrs65
Copy link
Contributor Author

jrs65 commented Apr 19, 2021

@ssiegelx @wulfda02 as this doesn't effect any existing functionality (and you have your own updates to), I'd like to get this very quickly reviewed and merged into master, and then we can work on getting your changes merged on top.

@@ -230,7 +231,7 @@ def process(self, gstream):
vmax = nsmax / wv

if self.weight == "inverse_variance":
gw = gsw[:, lfi].copy()
gw = gsw[:, lfi].view(np.ndarray).copy()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the view() occur before the slice?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point. This is fine with the current mpiarray code, but would result in a warning in the new one. Probably the right thing to do is to define gsw with a .local_array, but we'll need the new code to get merged first and I'm still a little reticent to do it atm.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that both .local_array and moving the view before the slice is old-code compatible!

Copy link
Contributor

@ssiegelx ssiegelx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrs65 I think I've identified one bug described in the comment above.

Beyond that, all of my suggestions are implemented in PR #126.

# Get the effective beamwidth for the polarisation combination
sig_a = beam_width[pa](freq, dec)
sig_b = beam_width[pb](freq, dec)
sig = sig_a * sig_b / (sig_a ** 2 + sig_b ** 2) ** 0.5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the order of operations that you expect here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

??

…sh` routine

Due to some of the logic handling whether the method exists or not, it
would mask and silence an AttributeError that was raised for other reasons in the
actual `.process_finish` method when it ran.
Transform wasn't exactly invertible as mmax was incorrect.
@jrs65 jrs65 marked this pull request as ready for review April 20, 2021 03:27
@jrs65 jrs65 merged commit 46fa146 into master Apr 20, 2021
@jrs65 jrs65 deleted the deconvolving-ringmap branch April 20, 2021 03:28
@lgtm-com
Copy link

lgtm-com bot commented Apr 20, 2021

This pull request fixes 1 alert when merging 09a9fe1 into 63e68d4 - view on LGTM.com

fixed alerts:

  • 1 for Unnecessary pass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants