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

Refactor for SoLikeT #86

Merged
merged 53 commits into from
Sep 4, 2024
Merged

Refactor for SoLikeT #86

merged 53 commits into from
Sep 4, 2024

Conversation

cmbant
Copy link
Collaborator

@cmbant cmbant commented Aug 1, 2024

Currently there are two different versions of MFLike (on separate git repos), SOLikeT and this, which is confusing and hard to maintain. This attempts to merge the two, with the objective of deleting the version in SOLikeT so we don't have any code duplication.

Basically it splits of BandpowerForeground as a separate Theory, allowing the foreground model to be swapped in and out, and the foreground and calibration/systematic parameters to be sampled separately. At the moment it doesn't split into a separate bandpower theory as in the current SOLikeT, and here TheoryForge obolished by replacing with the foreground model or merging into mflike.

pspipe_utils can now use BandpowerForeground instead of TheoryForge as in simonsobs/pspipe_utils#53.

@cmbant cmbant mentioned this pull request Aug 1, 2024
@codecov-commenter
Copy link

codecov-commenter commented Aug 1, 2024

Codecov Report

Attention: Patch coverage is 84.96732% with 46 lines in your changes missing coverage. Please review.

Please upload report for BASE (master@660e0fa). Learn more about missing BASE report.

Files Patch % Lines
mflike/mflike.py 77.77% 26 Missing ⚠️
mflike/foreground.py 89.24% 20 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##             master      #86   +/-   ##
=========================================
  Coverage          ?   85.24%           
=========================================
  Files             ?        3           
  Lines             ?      454           
  Branches          ?        0           
=========================================
  Hits              ?      387           
  Misses            ?       67           
  Partials          ?        0           
Files Coverage Δ
mflike/__init__.py 71.42% <100.00%> (ø)
mflike/foreground.py 89.24% <89.24%> (ø)
mflike/mflike.py 82.75% <77.77%> (ø)

Copy link
Collaborator

@xgarrido xgarrido left a comment

Choose a reason for hiding this comment

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

I do not see any problems to merge this PR. It provides a lot of improvements for mflike itself and I guess it will ease the integration into SOLikeT.

logp += self.logp_const
self.log.debug(
f"Log-likelihood value computed = {logp} (Χ² = {-2 * (logp - self.logp_const)})"
f"Log-likelihood value computed = {logp} (Χ² = {-2 * (- self.logp_const)})"
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the second logp has been lost when computing the chi-square value. Maybe we can write it

chi2 = self._fast_chi_squared(self.inv_cov, delta)
logp = -0.5 * chi2 + self.logp_const
self.log.debug(f"Log-likelihood value computed = {logp} (Χ² = {chi2})")

if ell is None:
ell = self.ells
model = self._get_foreground_model_arrays(fg_params, ell=ell)
experiments = self.experiments if freqs_order is None else freqs_order
Copy link
Collaborator

Choose a reason for hiding this comment

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

experiments = freqs_order or self.experiments

is simpler I guess

# get total foregrounds; model is dictionary of arrays for each frequency combo
model = self._get_foreground_model_arrays(params_values_dict)
return [np.sum([model[s, comp] for comp in self.fg_component_list[s]], axis=0)
for s in (requested_cl if requested_cl else self.requested_cls)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here also can be written

for s in requested_cl or self.requested_cls

it's up to you.
I wonder if it is better (or not) to set the requested_cl function argument to None or leave it as empty tuple (the above code works in both cases)

return self.current_state["fg_totals"]

def must_provide(self, **requirements):
if (req := requirements.get("fg_totals")) is not None:
Copy link
Collaborator

Choose a reason for hiding this comment

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

if req := requirements.get("fg_totals"):

# Foreground requires bandint_freqs from BandPass
# TODO: not clear that changing number of freqs actually works (for shift parameters)
super().must_provide(**requirements)
if (req := requirements.get("fg_totals")) is not None:
Copy link
Collaborator

Choose a reason for hiding this comment

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

same as before

@cmbant
Copy link
Collaborator Author

cmbant commented Sep 3, 2024

Agree on logp. I try to avoid comparing sequences that might be an np.ndarray, because bool(ndarray) raises an exception if the array is not empty, hence explicit comparisons to None

@cmbant cmbant merged commit 37048c1 into master Sep 4, 2024
11 checks passed
@cmbant cmbant deleted the restructure branch September 4, 2024 07:56
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