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

Ch/psestimate memory #91

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
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: 1 addition & 0 deletions drift/core/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"Full": psestimation.PSExact,
"MonteCarlo": psmc.PSMonteCarlo,
"MonteCarloAlt": psmc.PSMonteCarloAlt,
"MonteCarloLarge": psmc.PSMonteCarloLarge,
"Cross": crosspower.CrossPower,
}

Expand Down
91 changes: 66 additions & 25 deletions drift/core/psestimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,11 +506,18 @@ def generate(self, regen=False):
self.fisher = mpiutil.allreduce(fisher_loc, op=MPI.SUM)
self.bias = mpiutil.allreduce(bias_loc, op=MPI.SUM)

# Write out all the PS estimation products
if mpiutil.rank0:
et = time.time()
logger.info(f"======== Ending PS calculation (time={et - st:f}) ========")

self.write_fisher_file()

# ===================================================

def write_fisher_file(self):
"""Write PS estimation products into hdf5 file"""
# Write out all the PS estimation products
if mpiutil.rank0:
# Check to see ensure that Fisher matrix isn't all zeros.
if not (self.fisher == 0).all():
# Generate derived quantities (covariance, errors..)
Expand Down Expand Up @@ -559,8 +566,6 @@ def generate(self, regen=False):

f.close()

# ===================================================

def fisher_file(self):
"""Fetch the h5py file handle for the Fisher matrix.

Expand All @@ -579,31 +584,25 @@ def fisher_bias(self):

# ====== Estimate the q-parameters from data ========

def q_estimator(self, mi, vec1, vec2=None, noise=False):
"""Estimate the q-parameters from given data (see paper).

def project_vector_kl_to_sky(self, mi, vec1):
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as before: should this go in drift.core.kltransform instead of drift.core.psestimation?

"""
Parameters
----------
mi : integer
The m-mode we are calculating for.
vec : np.ndarray[num_kl, num_realisatons]
The vector(s) of data we are estimating from. These are KL-mode
coefficients.
noise : boolean, optional
Whether we should project against the noise matrix. Used for
estimating the bias by Monte-Carlo. Default is False.
M-mode index to fetch for.
vec1 : np.ndarray
The vector of data in the KL-basis packed as [num_kl, num_realisatons].

Returns
-------
qa : np.ndarray[numbands]
Array of q-parameters. If noise=True then the array is one longer,
and the last parameter is the projection against the noise.
x2 : np.ndarray
The vector of data in the sky basis packed as [nfreq, lmax+1, num_realisations]
"""

evals, evecs = self.kltrans.modes_m(mi)

if evals is None:
return np.zeros((self.nbands + 1 if noise else self.nbands,))
return np.zeros((0,), dtype=np.complex128)

# Weight by C**-1 (transposes are to ensure broadcast works for 1 and 2d vecs)
x0 = (vec1.T / (evals + 1.0)).T
Expand All @@ -612,16 +611,44 @@ def q_estimator(self, mi, vec1, vec2=None, noise=False):
x1 = np.dot(evecs.T.conj(), x0)

# Project back into sky basis
x2 = self.kltrans.beamtransfer.project_vector_svd_to_sky(mi, x1, conj=True)
x2 = self.kltrans.beamtransfer.project_vector_svd_to_sky(
mi, x1, temponly=True, conj=True
sjforeman marked this conversation as resolved.
Show resolved Hide resolved
)
# Slice array for temponly
x2 = x2[:, 0]

return x2

def q_estimator(self, mi, vec1, vec2=None, noise=False):
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that you have an entirely new implementation of q_estimator in your new class, why does the old one need to get changed?

Copy link
Author

Choose a reason for hiding this comment

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

I wanted to factor out the part of the code that projects from KL-basis to sky basis so that it can be reused as a method in the future.

Copy link
Author

Choose a reason for hiding this comment

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

and the new PS-code would get just like a big spaghetti code. Tried to factor out as much as I could.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, makes sense to me

"""Estimate the q-parameters from given data (see paper).

Parameters
----------
mi : integer
The m-mode we are calculating for.
vec1, vec2 : np.ndarrays[num_kl, num_realisatons]
The vector(s) of data we are estimating from. These are KL-mode coefficients. Passing in `vec2` is optional and for cross power spectrum calculation.
noise : boolean, optional
Whether we should project against the noise matrix. Used for
estimating the bias by Monte-Carlo. Default is False.

Returns
-------
qa : np.ndarray[numbands]
Array of q-parameters. If noise=True then the array is one longer,
and the last parameter is the projection against the noise.
"""

x2 = self.project_vector_kl_to_sky(mi, vec1)

if vec2 is not None:
y0 = (vec2.T / (evals + 1.0)).T
y1 = np.dot(evecs.T.conj(), x0)
y2 = self.kltrans.beamtransfer.project_vector_svd_to_sky(mi, x1, conj=True)
y2 = self.project_vector_kl_to_sky(mi, vec2)
else:
y0 = x0
y2 = x2

if (x2.shape[0], y2.shape[0]) == (0, 0):
return np.zeros((self.nbands + 1 if noise else self.nbands,))

# Create empty q vector (length depends on if we're calculating the noise term too)
qa = np.zeros((self.nbands + 1 if noise else self.nbands,) + vec1.shape[1:])

Expand All @@ -630,8 +657,9 @@ def q_estimator(self, mi, vec1, vec2=None, noise=False):
# Calculate q_a for each band
for bi in range(self.nbands):
for li in range(lside):
lxvec = x2[:, 0, li]
lyvec = y2[:, 0, li]

lxvec = x2[:, li]
lyvec = y2[:, li]
sjforeman marked this conversation as resolved.
Show resolved Hide resolved

qa[bi] += np.sum(
lyvec.conj()
Expand All @@ -643,10 +671,22 @@ def q_estimator(self, mi, vec1, vec2=None, noise=False):

# Calculate q_a for noise power (x0^H N x0 = |x0|^2)
if noise:
evals, evecs = self.kltrans.modes_m(mi)

if evals is None:
return np.zeros((self.nbands + 1))

# If calculating crosspower don't include instrumental noise
noisemodes = 0.0 if self.crosspower else 1.0
noisemodes = noisemodes + (evals if self.zero_mean else 0.0)

x0 = (vec1.T / (evals + 1.0)).T

if vec2 is not None:
y0 = (vec2.T / (evals + 1.0)).T
else:
y0 = x0

qa[-1] = np.sum((x0 * y0.conj()).T.real * noisemodes, axis=-1)

return qa.real
Expand All @@ -655,7 +695,8 @@ def q_estimator(self, mi, vec1, vec2=None, noise=False):


class PSExact(PSEstimation):
"""PS Estimation class with exact calculation of the Fisher matrix."""
"""PS Estimation class with exact calculation of the Fisher matrix.
"""

@property
def _cfile(self):
Expand Down
Loading
Loading