Skip to content
Merged
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
32 changes: 1 addition & 31 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,4 @@ jobs:
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: coverage.py badge
uses: tj-actions/coverage-badge-py@v2.0.3
- name: Verify Changed files
uses: tj-actions/verify-changed-files@v20
id: verify-changed-files
with:
files: coverage.svg
- name: Commit files
if: steps.verify-changed-files.outputs.files_changed == 'true'
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add coverage.svg
git commit -m "Updated coverage.svg"
- name: Push changes
if: steps.verify-changed-files.outputs.files_changed == 'true'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.github_token }}
branch: ${{ github.ref }}
- name: Re-pull on failure
if: ${{ failure() }}
run: git pull origin ${{ github.ref }} --autostash --rebase -X ours
- name: Re-push on failure
if: ${{ failure() }}
uses: ad-m/github-push-action@master
with:
branch: ${{ github.ref }}
force: true
github_token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.CODECOV_TOKEN }}
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1.2.1 : Updating configs of other surveys: SKAO, DESI, LSST to work in new config file structure
1.2.2 : Galaxy sample split for sources and lenses. Feedback prints more consistent.
1.2.3 : Added a new likelihood function for photometric and spectroscopic surveys.
1.2.4 : Discontinued support for python3.8. Fixed the style for likelihood scripts.
1.2.4 : Discontinued support for python3.8. Fixed the style for likelihood scripts.
1.2.5 : Likelihood modules tested for photo and spectro
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# cosmicfishpie

[![Documentation Status](https://readthedocs.org/projects/cosmicfishpie/badge/?version=latest)](https://cosmicfishpie.readthedocs.io/en/latest/?badge=latest)
![Coverage](./coverage.svg) [![codecov](https://codecov.io/github/santiagocasas/cosmicfishpie/graph/badge.svg?token=BXTVDPXPUO)](https://codecov.io/github/santiagocasas/cosmicfishpie)
[![codecov](https://codecov.io/github/santiagocasas/cosmicfishpie/graph/badge.svg?token=BXTVDPXPUO)](https://codecov.io/github/santiagocasas/cosmicfishpie)
[![37.50 % FAIR](https://img.shields.io/badge/FAIR_assessment-37.50_%25-red)](https://fair-checker.france-bioinformatique.fr/assessment/68da9e3cc49e421b3e2cf501)


See CITATION.cff for citation metadata.
See [`CITATION.cff`](CITATION.cff) for citation metadata or click on the "Cite this repository" button on the sidebar.

<div align="center">
<img src="https://github.com/santiagocasas/cosmicfishpie/assets/6987716/1816b3b7-0920-4a2c-aafd-9c4ba1dc3e2b" width="280">
Expand Down
4 changes: 2 additions & 2 deletions cosmicfishpie/analysis/fishconsumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def fishtable_to_pandas(
if ff.name in filter_names:
newname = ff.name.split(" ")[0]
# print(newname)
ltxname = "$\\mathrm{" + str(newname).replace(" ", "\ ") + "}$"
ltxname = "$\\mathrm{" + str(newname).replace(" ", "\\ ") + "}$"
barplot_data[ltxname] = rel_err
if return_data_bar:
return barplot_data
Expand Down Expand Up @@ -586,7 +586,7 @@ def prepare_settings_plot(
.replace(r"\,", "-")
.replace("$", "")
.replace(r"\\", "")
.replace("\mathrm", "")
.replace("\\mathrm", "")
.replace("___", "_")
.replace("__", "_")
.replace("----", "-")
Expand Down
7 changes: 7 additions & 0 deletions cosmicfishpie/likelihood/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
Likelihood subpackage: tools to compute data/theory spectra and chi2.
"""

from .base import Likelihood # noqa: F401
from .photo_like import PhotometricLikelihood # noqa: F401
from .spectro_like import SpectroLikelihood # noqa: F401
220 changes: 220 additions & 0 deletions cosmicfishpie/likelihood/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
"""Base infrastructure for likelihood modules in Cosmicfishpie.

This module provides the core interface and utilities for implementing
likelihood calculations in Cosmicfishpie, particularly for cosmological
parameter estimation using Fisher matrices.
"""

from __future__ import annotations

from abc import ABC, abstractmethod
from collections.abc import Sequence
from typing import Any, Dict, Iterable, Optional

import numpy as np
from nautilus import Prior, Sampler

from cosmicfishpie.fishermatrix.cosmicfish import FisherMatrix


def is_indexable_iterable(var: Any) -> bool:
"""Check if a variable is an indexable iterable.

Args:
var: The variable to check

Returns:
bool: True if the variable is an indexable iterable (list, numpy array, or Sequence)
and not a string or bytes object, False otherwise.
"""
return isinstance(var, (list, np.ndarray, Sequence)) and not isinstance(var, (str, bytes))


class Likelihood(ABC):
"""Common interface for likelihood evaluations used in Cosmicfishpie.

This abstract base class defines the core interface for likelihood calculations
in Cosmicfishpie. It provides methods for computing data representations,
theory predictions, and chi-squared values, as well as utilities for parameter
handling and running Nautilus samplers.
"""

def __init__(
self,
*,
cosmo_data: FisherMatrix,
cosmo_theory: Optional[FisherMatrix] = None,
leg_flag: str = "wedges",
) -> None:
"""Initialize the Likelihood object with Fisher matrices.

Args:
cosmo_data: FisherMatrix object containing the observed data
cosmo_theory: Optional FisherMatrix object for theory predictions.
If None, uses cosmoFM_data
leg_flag: Flag indicating the type of data representation to use
("wedges" or other supported types)
"""
self.cosmo_data = cosmo_data
self.cosmo_theory = cosmo_theory or cosmo_data
self.leg_flag = leg_flag
self.data_obs = self.compute_data()

@abstractmethod
def compute_data(self) -> Any:
"""Compute and return the observed data representation.

This method should be implemented by subclasses to return the data
in the appropriate format (e.g., wedges or multipoles) for likelihood
calculations.

Returns:
The observed data representation
"""

@abstractmethod
def compute_theory(self, param_dict: Dict[str, Any]) -> Any:
"""Compute and return the theory prediction.

This method should be implemented by subclasses to return the theory
prediction in the same representation as the observed data.

Args:
param_dict: Dictionary of cosmological parameters

Returns:
The theory prediction in the same format as the observed data
"""

@abstractmethod
def compute_chi2(self, theory_obs: Any) -> float:
"""Compute and return the chi-squared value.

This method should be implemented by subclasses to compute the chi-squared
value between the observed data and theory prediction.

Args:
theory_obs: Theory prediction in the same format as observed data

Returns:
The chi-squared value
"""

def build_param_dict(
self,
*,
param_vec: Optional[Iterable[float]] = None,
param_dict: Optional[Dict[str, Any]] = None,
prior: Optional[Any] = None,
) -> Dict[str, Any]:
"""Create a parameter dictionary from vector inputs when needed.

This method converts a parameter vector to a dictionary using the prior
information, or returns the provided parameter dictionary directly.

Args:
param_vec: Optional iterable of parameter values
param_dict: Optional dictionary of parameters
prior: Optional prior information for parameter mapping

Returns:
Dictionary of parameters

Raises:
ValueError: If neither param_dict nor (param_vec and prior) are provided
TypeError: If param_vec is not an indexable iterable
AttributeError: If prior object doesn't expose an ordered 'keys' attribute
"""
if param_dict is not None:
return dict(param_dict)

if param_vec is None or prior is None:
raise ValueError(
"Provide either param_dict or (param_vec and prior) to build the parameter mapping"
)

if not is_indexable_iterable(param_vec):
raise TypeError(
"param_vec must be an indexable iterable when no param_dict is supplied"
)

prior_keys = getattr(prior, "keys", None)
if prior_keys is None:
raise AttributeError(
"prior object must expose an ordered 'keys' attribute to map the vector to parameters"
)

return {key: param_vec[i] for i, key in enumerate(prior_keys)}

def loglike(
self,
param_vec: Optional[Iterable[float]] = None,
*,
param_dict: Optional[Dict[str, Any]] = None,
prior: Optional[Any] = None,
) -> float:
"""Compute the log-likelihood value.

This method computes the log-likelihood value (-0.5 * χ²) for the
supplied parameters. It can accept either a parameter vector or a
parameter dictionary.

Args:
param_vec: Optional iterable of parameter values
param_dict: Optional dictionary of parameters
prior: Optional prior information for parameter mapping

Returns:
The log-likelihood value (-0.5 * χ²)
"""
params = self.build_param_dict(param_vec=param_vec, param_dict=param_dict, prior=prior)
theory_obs = self.compute_theory(params)
chi2 = self.compute_chi2(theory_obs)
return -0.5 * chi2


class NautilusMixin:
"""Mixin class for running Nautilus samplers."""

def create_nautilus_prior(self, prior_dict: Dict[str, Any]) -> Prior:
"""Create a Nautilus prior object from a dictionary of parameter names and their prior ranges.

Args:
prior_dict: Dictionary of parameter names and their prior ranges

Returns:
Nautilus Prior object
"""

prior = Prior()
for par, (lower, upper) in prior_dict.items():
prior.add_parameter(par, (lower, upper))
return prior

def run_nautilus(
self,
*,
prior: Any,
sampler_kwargs: Optional[Dict[str, Any]] = None,
run_kwargs: Optional[Dict[str, Any]] = None,
) -> Sampler:
"""Convenience wrapper to launch a Nautilus sampler using this likelihood.

This method provides a convenient interface to run Nautilus samplers
with the current likelihood function.

Args:
prior: Prior information for the parameters
sampler_kwargs: Optional dictionary of keyword arguments for the Sampler
run_kwargs: Optional dictionary of keyword arguments for the run method

Returns:
The Nautilus Sampler object
"""

sampler_kwargs = dict(sampler_kwargs or {})
run_kwargs = dict(run_kwargs or {})

sampler = Sampler(prior, self.loglike, **sampler_kwargs, likelihood_kwargs={"prior": prior})
sampler.run(**run_kwargs)
return sampler
Loading