Skip to content

nullpol.analysis.likelihood

nullpol.analysis.likelihood

Likelihood package.

nullpol.analysis.likelihood.Chi2TimeFrequencyLikelihood

Bases: TimeFrequencyLikelihood

A time-frequency likelihood class that computes the likelihood of the total null energy.

Parameters:

Name Type Description Default
interferometers list

List of interferometers.

required
wavelet_frequency_resolution float

The frequency resolution of the wavelet transform.

required
wavelet_nx int

The number of points in the wavelet transform.

required
polarization_modes list

List of polarization modes.

required
polarization_basis list

List of polarization basis.

None
time_frequency_filter str

The time-frequency filter.

None
Source code in src/nullpol/analysis/likelihood/chi2_tf_likelihood.py
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
class Chi2TimeFrequencyLikelihood(TimeFrequencyLikelihood):
    """A time-frequency likelihood class that computes the likelihood of the total null energy.

    Args:
        interferometers (list): List of interferometers.
        wavelet_frequency_resolution (float): The frequency resolution of the wavelet transform.
        wavelet_nx (int): The number of points in the wavelet transform.
        polarization_modes (list): List of polarization modes.
        polarization_basis (list): List of polarization basis.
        time_frequency_filter (str): The time-frequency filter.
    """

    def __init__(
        self,
        interferometers,
        wavelet_frequency_resolution,
        wavelet_nx,
        polarization_modes,
        *args,
        polarization_basis=None,
        time_frequency_filter=None,
        **kwargs,
    ):
        """Initialize the instance."""
        super().__init__(
            *args,
            interferometers=interferometers,
            wavelet_frequency_resolution=wavelet_frequency_resolution,
            wavelet_nx=wavelet_nx,
            polarization_modes=polarization_modes,
            polarization_basis=polarization_basis,
            time_frequency_filter=time_frequency_filter,
            **kwargs,
        )

    @property
    def DoF(self):
        """Degree of freedom.

        Returns:
            int: Degree of freedom.
        """
        polarization_basis_sum = np.sum(self.antenna_pattern_processor.polarization_basis)

        if self.data_context.time_frequency_filter is None:
            raise ValueError("Time frequency filter is not available")

        time_frequency_filter_sum = np.sum(self.data_context.time_frequency_filter)
        return (len(self.interferometers) - polarization_basis_sum) * time_frequency_filter_sum

    def log_likelihood(self, parameters=None):
        """Compute the log likelihood using the supplied parameters.

        Args:
            parameters (dict, optional): Proposal parameters supplied by the sampler.
                If None, Bilby's deprecated fallback to ``self.parameters`` applies.
        """
        parameters = _fallback_to_parameters(self, parameters)
        # Compute null energy using the parameters
        null_energy = self.null_stream_calculator.compute_null_energy(parameters)

        return scipy.stats.chi2.logpdf(null_energy, df=self.DoF)

    def _calculate_noise_log_likelihood(self):
        """Calculate the noise log likelihood.

        Returns:
            float: noise log likelihood.
        """
        if self.data_context.whitened_frequency_domain_strain_array is None:
            raise ValueError("Whitened frequency domain strain array is not available")
        if self.data_context.time_frequency_filter is None:
            raise ValueError("Time frequency filter is not available")

        wavelet_domain_strain_array = np.array(
            [
                transform_wavelet_freq(
                    data=self.data_context.whitened_frequency_domain_strain_array[i],
                    sampling_frequency=self.data_context.sampling_frequency,
                    frequency_resolution=self.data_context.wavelet_frequency_resolution,
                    nx=self.data_context.wavelet_nx,
                )
                for i in range(len(self.interferometers))
            ]
        )
        E = np.sum(np.abs(wavelet_domain_strain_array * self.data_context.time_frequency_filter) ** 2)
        log_likelihood = scipy.stats.chi2.logpdf(
            E, df=len(self.interferometers) * np.sum(self.data_context.time_frequency_filter)
        )
        return log_likelihood

nullpol.analysis.likelihood.Chi2TimeFrequencyLikelihood.data_context property

Access to the data context through null_stream_calculator.

Returns:

Name Type Description
TimeFrequencyDataContext

The data context instance.

nullpol.analysis.likelihood.Chi2TimeFrequencyLikelihood.antenna_pattern_processor property

Access to the antenna pattern processor through null_stream_calculator.

Returns:

Name Type Description
AntennaPatternProcessor

The antenna pattern processor instance.

nullpol.analysis.likelihood.Chi2TimeFrequencyLikelihood.interferometers property

A list of interferometers.

Returns:

Type Description

bilby.gw.detector.InterferometerList: A list of interferometers.

nullpol.analysis.likelihood.Chi2TimeFrequencyLikelihood.DoF property

Degree of freedom.

Returns:

Name Type Description
int

Degree of freedom.

nullpol.analysis.likelihood.Chi2TimeFrequencyLikelihood.noise_log_likelihood()

Compute the noise log likelihood.

Returns:

Name Type Description
float

The noise log likelihood.

Source code in src/nullpol/analysis/likelihood/time_frequency_likelihood.py
110
111
112
113
114
115
116
117
118
def noise_log_likelihood(self):
    """Compute the noise log likelihood.

    Returns:
        float: The noise log likelihood.
    """
    if self._noise_log_likelihood_value is None:
        self._noise_log_likelihood_value = self._calculate_noise_log_likelihood()
    return self._noise_log_likelihood_value

nullpol.analysis.likelihood.Chi2TimeFrequencyLikelihood.log_likelihood(parameters=None)

Compute the log likelihood using the supplied parameters.

Parameters:

Name Type Description Default
parameters dict

Proposal parameters supplied by the sampler. If None, Bilby's deprecated fallback to self.parameters applies.

None
Source code in src/nullpol/analysis/likelihood/chi2_tf_likelihood.py
64
65
66
67
68
69
70
71
72
73
74
75
def log_likelihood(self, parameters=None):
    """Compute the log likelihood using the supplied parameters.

    Args:
        parameters (dict, optional): Proposal parameters supplied by the sampler.
            If None, Bilby's deprecated fallback to ``self.parameters`` applies.
    """
    parameters = _fallback_to_parameters(self, parameters)
    # Compute null energy using the parameters
    null_energy = self.null_stream_calculator.compute_null_energy(parameters)

    return scipy.stats.chi2.logpdf(null_energy, df=self.DoF)

nullpol.analysis.likelihood.TimeFrequencyLikelihood

Bases: Likelihood

A time-frequency likelihood class with modular architecture.

This class uses composition to separate concerns: - Data management and antenna pattern operations are handled by NullStreamCalculator - Null stream computations are handled by NullStreamCalculator

For low-level data access, use: likelihood.null_stream_calculator.data_context.property_name For antenna pattern operations, use: likelihood.null_stream_calculator.antenna_pattern_processor.method_name For null stream computations, use: likelihood.null_stream_calculator.method_name For high-level likelihood operations, use the methods on this class directly.

Parameters:

Name Type Description Default
interferometers list

List of interferometers.

required
wavelet_frequency_resolution float

The frequency resolution of the wavelet transform.

required
wavelet_nx int

The number of points in the wavelet transform.

required
polarization_modes list

List of polarization modes.

required
polarization_basis list

List of polarization basis.

None
time_frequency_filter str

The time-frequency filter.

None
Source code in src/nullpol/analysis/likelihood/time_frequency_likelihood.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
class TimeFrequencyLikelihood(Likelihood):
    """A time-frequency likelihood class with modular architecture.

    This class uses composition to separate concerns:
    - Data management and antenna pattern operations are handled by NullStreamCalculator
    - Null stream computations are handled by NullStreamCalculator

    For low-level data access, use: likelihood.null_stream_calculator.data_context.property_name
    For antenna pattern operations, use: likelihood.null_stream_calculator.antenna_pattern_processor.method_name
    For null stream computations, use: likelihood.null_stream_calculator.method_name
    For high-level likelihood operations, use the methods on this class directly.

    Args:
        interferometers (list): List of interferometers.
        wavelet_frequency_resolution (float): The frequency resolution of the wavelet transform.
        wavelet_nx (int): The number of points in the wavelet transform.
        polarization_modes (list): List of polarization modes.
        polarization_basis (list): List of polarization basis.
        time_frequency_filter (str): The time-frequency filter.
    """

    def __init__(
        self,
        interferometers,
        wavelet_frequency_resolution,
        wavelet_nx,
        polarization_modes,
        *args,  # pylint: disable=unused-argument
        polarization_basis=None,
        time_frequency_filter=None,
        **kwargs,  # pylint: disable=unused-argument
    ):
        """Initialize the instance."""
        super().__init__()

        # Initialize null stream calculator with all components
        self.null_stream_calculator = NullStreamCalculator(
            interferometers=interferometers,
            wavelet_frequency_resolution=wavelet_frequency_resolution,
            wavelet_nx=wavelet_nx,
            polarization_modes=polarization_modes,
            polarization_basis=polarization_basis,
            time_frequency_filter=time_frequency_filter,
        )

        # Initialize the normalization constant
        self._noise_log_likelihood_value = None

        # Marginalization
        self._marginalized_parameters = []

    @property
    def data_context(self):
        """Access to the data context through null_stream_calculator.

        Returns:
            TimeFrequencyDataContext: The data context instance.
        """
        return self.null_stream_calculator.data_context

    @property
    def antenna_pattern_processor(self):
        """Access to the antenna pattern processor through null_stream_calculator.

        Returns:
            AntennaPatternProcessor: The antenna pattern processor instance.
        """
        return self.null_stream_calculator.antenna_pattern_processor

    @property
    def interferometers(self):
        """A list of interferometers.

        Returns:
            bilby.gw.detector.InterferometerList: A list of interferometers.
        """
        return self.null_stream_calculator.data_context.interferometers

    def log_likelihood(self, parameters=None):
        """Log likelihood.

        Args:
            parameters (dict, optional): Proposal parameters supplied by the sampler.

        Raises:
            NotImplementedError: This should be implemented in a subclass.
        """
        raise NotImplementedError("The log_likelihood method must be implemented in a subclass.")

    def _calculate_noise_log_likelihood(self):
        """Calculate noise log likelihood.

        This should be implemented in a subclass.

        Raises:
            NotImplementedError: This should be implemented in a subclass.
        """
        raise NotImplementedError("The _calculate_noise_log_likelihood method must be implemented in a subclass.")

    def noise_log_likelihood(self):
        """Compute the noise log likelihood.

        Returns:
            float: The noise log likelihood.
        """
        if self._noise_log_likelihood_value is None:
            self._noise_log_likelihood_value = self._calculate_noise_log_likelihood()
        return self._noise_log_likelihood_value

nullpol.analysis.likelihood.TimeFrequencyLikelihood.data_context property

Access to the data context through null_stream_calculator.

Returns:

Name Type Description
TimeFrequencyDataContext

The data context instance.

nullpol.analysis.likelihood.TimeFrequencyLikelihood.antenna_pattern_processor property

Access to the antenna pattern processor through null_stream_calculator.

Returns:

Name Type Description
AntennaPatternProcessor

The antenna pattern processor instance.

nullpol.analysis.likelihood.TimeFrequencyLikelihood.interferometers property

A list of interferometers.

Returns:

Type Description

bilby.gw.detector.InterferometerList: A list of interferometers.

nullpol.analysis.likelihood.TimeFrequencyLikelihood.log_likelihood(parameters=None)

Log likelihood.

Parameters:

Name Type Description Default
parameters dict

Proposal parameters supplied by the sampler.

None

Raises:

Type Description
NotImplementedError

This should be implemented in a subclass.

Source code in src/nullpol/analysis/likelihood/time_frequency_likelihood.py
89
90
91
92
93
94
95
96
97
98
def log_likelihood(self, parameters=None):
    """Log likelihood.

    Args:
        parameters (dict, optional): Proposal parameters supplied by the sampler.

    Raises:
        NotImplementedError: This should be implemented in a subclass.
    """
    raise NotImplementedError("The log_likelihood method must be implemented in a subclass.")

nullpol.analysis.likelihood.TimeFrequencyLikelihood.noise_log_likelihood()

Compute the noise log likelihood.

Returns:

Name Type Description
float

The noise log likelihood.

Source code in src/nullpol/analysis/likelihood/time_frequency_likelihood.py
110
111
112
113
114
115
116
117
118
def noise_log_likelihood(self):
    """Compute the noise log likelihood.

    Returns:
        float: The noise log likelihood.
    """
    if self._noise_log_likelihood_value is None:
        self._noise_log_likelihood_value = self._calculate_noise_log_likelihood()
    return self._noise_log_likelihood_value