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

FFTPower mu-edges #663

Open
adematti opened this issue Jan 11, 2022 · 3 comments
Open

FFTPower mu-edges #663

adematti opened this issue Jan 11, 2022 · 3 comments

Comments

@adematti
Copy link
Collaborator

adematti commented Jan 11, 2022

Hi,

I think there is an issue with current FFTPower implementation (0.3.16dev0);
muedges (now) range from -1 to 1 as set in:

muedges = numpy.linspace(-1, 1, self.attrs['Nmu']+1, endpoint=True)

In most cases one will paint positions and weights on a real mesh
def to_mesh(self, Nmesh=None, BoxSize=None, dtype='f4', interlaced=False,

Hence, hermitian symmetry is exploited to use only kz >= 0 modes.
When line-of-sight is z, mu obtained by
mu = slab.mu(los) # defined with respect to specified LOS

will always be > 0. Hence wedges at mu < 0 are empty (NaN power).
I guess one could either (by order of increased code changes):
a) drop Hermitian symmetry by defaulting to complex field as has been done for FKPCatalog, but this is overkill
b) revert to muedges in [0, 1], and take abs(mu) in case of Hermitian symmetry
c) keep muedges in [-1, 1], and create mu < 0 modes on-the-fly in project_to_basis.

Note: about odd poles in FKP estimator, instead of switching to full complex field, one can just use Hermitian antisymmetry in project_to_basis.
Note: in case single precision is used, some (k, mu) modes fall in the wrong bin. Casting slab coordinates to 'f8' around here:

xslab = slab.norm2()

resolves this problem and increases accuracy in the estimated power spectrum at low memory cost.

Another, quite unrelated question: I though that, within pmesh, a particles are "painted" on the mesh nodes,
i.e. not in cell centers. So I do not understand that extra half-cell shift (0.5*pm.BoxSize / pm.Nmesh) here:

offset = self.attrs['BoxCenter'] + 0.5*pm.BoxSize / pm.Nmesh

  • I'd have naively taken coordinates at the grid nodes, without this cell-shift. Am I missing something?

Thanks!

@rainwoodman
Copy link
Member

Thanks for the reports.

Yes I agree there seems to be a NaN problem. Do you have a simple notebook to reproduce this?

For a fix, perhaps this line:

6ab5a06#diff-bf846022d2da880aa1441037073fa99e26bdde9b7b720c4cc2e15504a3d95aa4R571

shall used y3d.compressed instead of False. If compressed is True then there is no mu < 0 values, and we shall use the hermitian symmetric block. Setting it to False regardless of the input is compressed was incorrect.

The 'symmetric' vs 'anti-symmetric' treatment you are probably referring to this?
6ab5a06#diff-bf846022d2da880aa1441037073fa99e26bdde9b7b720c4cc2e15504a3d95aa4R648

Round off errors(f8): That's reasonable. Could you file a Pull request?

Offset of half of grid: Indeed that shift is weird. I agree with you that eliminating it makes sense. Did you check how much eliminating the shift affects the results?

@adematti
Copy link
Collaborator Author

adematti commented Jan 22, 2022

Sorry for the delay,

The line you quote (6ab5a06#diff-bf846022d2da880aa1441037073fa99e26bdde9b7b720c4cc2e15504a3d95aa4R571) has been reverted back in ede93aa.
If compressed is True then there is no mu < 0 values => that depends on whether the line of sight is the same as the symmetry axis (x, y, z).
The issue appears when line-of-sight is z, in which case there are no mu < 0 values, hence empty mu < 0 wedges.
In other cases (line-of-sights x, y), the result looks about correct (even in this case there is actually some non-negligible difference of power between c16 and f8).

The issue is shown by this code snippet:

from nbodykit.lab import UniformCatalog, FFTPower

catalog = UniformCatalog(nbar=1e-4, BoxSize=1000.)
mesh = catalog.to_mesh(Nmesh=128, resampler='cic', interlaced=True, compensated=True)
power = FFTPower(mesh, mode='2d', Nmu=5, los=[0, 0, 1], dk=0.01)
print(power.power['power'][:,0])

For the 'symmetric' vs 'anti-symmetric' treatment, this is indeed linked to 6ab5a06.
But instead of using a complex mesh, one can stick to a real mesh and use that, given the quantity:
X_ell(k) = F_0(k) F_ell(k)* that is computed here:

A0_1[islab,...] = norm*A0_1[islab]*A0_2[islab].conj()

for odd poles X_ell(-k) = - X_ell(k)*.

Actually, casting coordinates to double precision here:


solves only ~ half of the wrong bin assignments. I guess that should be done when computing these coordinates, within pmesh itself?

About the shifts in ConvolvedFFTPower, it's a typical ~ 5% effect for the quadrupole, in the test case of https://github.com/bccp/nbodykit/blob/master/nbodykit/algorithms/tests/test_conv_power.py
(of course, no effect on the monopole, and a bit more for the hexadecapole).

@jegarfa
Copy link

jegarfa commented Jun 2, 2022

Hi, I just arrived to the same issue.
I was trying to reproduce one of the documentation examples, specifically the one that computes the 2D Power Spectrum.
I noticed the same behavior previous commented, the mu_edges are starting from -1 instead of 0.
Here I attached a notebook that reproduce the issue
[example notebook](https://github.com/jegarfa/Example_nbodykit/blob/main/Example_2D_Power_Spectrum.ipynb)

I am not sure if just by editing this line would be enough
6ab5a06#diff-bf846022d2da880aa1441037073fa99e26bdde9b7b720c4cc2e15504a3d95aa4R571
mu_edges
nbodykit_documentation_example

qezlou added a commit to qezlou/nbodykit that referenced this issue Sep 12, 2022
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

No branches or pull requests

3 participants