Source code for treecorr.kggcorrelation

# Copyright (c) 2003-2024 by Mike Jarvis
#
# TreeCorr is free software: redistribution and use in source and binary forms,
# with or without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions, and the disclaimer given in the accompanying LICENSE
#    file.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions, and the disclaimer given in the documentation
#    and/or other materials provided with the distribution.

"""
.. module:: nnncorrelation
"""

import numpy as np

from . import _treecorr
from .catalog import calculateVarK, calculateVarG
from .corr3base import Corr3


[docs]class KGGCorrelation(Corr3): r"""This class handles the calculation and storage of a 3-point scalar-shear-shear correlation function. With this class, point 1 of the triangle (i.e. the vertex opposite d1) is the one with the scalar value. Use `GKGCorrelation` and `GGKCorrelation` for classes with the scalar in the other two positions. For the shear projection, we follow the lead of the 3-point shear-shear-shear correlation functions (see `GGGCorrelation` for details), which involves projecting the shear values at each vertex relative to the direction to the triangle's centroid. Furthermore, the GGG correlations have 4 relevant complex values for each triangle: .. math:: \Gamma_0 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2}) \gamma(\mathbf{x3}) \rangle \\ \Gamma_1 &= \langle \gamma(\mathbf{x1})^* \gamma(\mathbf{x2}) \gamma(\mathbf{x3}) \rangle \\ \Gamma_2 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2})^* \gamma(\mathbf{x3}) \rangle \\ \Gamma_3 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2}) \gamma(\mathbf{x3}^*) \rangle \\ With a scalar value at vertex 1, :math:`\Gamma_0 = \Gamma_1` and :math:`\Gamma_2 = \Gamma_3^*`. So there are only two independent values. However, you may access these values using whichever names you find most convenient: ``gam0``, ``gam1``, ``gam2`` and ``gam3`` are all valid attributes, which return the corresponding value. See the doc string of `Corr3` for a description of how the triangles are binned along with the attributes related to the different binning options. In addition to the attributes common to all `Corr3` subclasses, objects of this class hold the following attributes: Attributes: gam0: The 0th "natural" correlation function, :math:`\Gamma_0`. gam1: The 1st "natural" correlation function, :math:`\Gamma_1`. gam2: The 2nd "natural" correlation function, :math:`\Gamma_2`. gam3: The 3rd "natural" correlation function, :math:`\Gamma_3`. vargam0: The variance estimate of :math:`\Gamma_0`, only including the shot noise. vargam1: The variance estimate of :math:`\Gamma_1`, only including the shot noise. vargam2: The variance estimate of :math:`\Gamma_2`, only including the shot noise. vargam3: The variance estimate of :math:`\Gamma_3`, only including the shot noise. The typical usage pattern is as follows:: >>> kgg = treecorr.KGGCorrelation(config) >>> kgg.process(cat1, cat2) # Compute cross-correlation of two fields. >>> kgg.process(cat1, cat2, cat3) # Compute cross-correlation of three fields. >>> kgg.write(file_name) # Write out to a file. >>> gam0 = kgg.gam0, etc. # Access gamma values directly. >>> gam0r = kgg.gam0r # Or access real and imag parts separately. >>> gam0i = kgg.gam0i Parameters: config (dict): A configuration dict that can be used to pass in kwargs if desired. This dict is allowed to have addition entries besides those listed in `Corr3`, which are ignored here. (default: None) logger: If desired, a logger object for logging. (default: None, in which case one will be built according to the config dict's verbose level.) Keyword Arguments: **kwargs: See the documentation for `Corr3` for the list of allowed keyword arguments, which may be passed either directly or in the config dict. """ _cls = 'KGGCorrelation' _letter1 = 'K' _letter2 = 'G' _letter3 = 'G' _letters = 'KGG' _builder = _treecorr.KGGCorr _calculateVar1 = staticmethod(calculateVarK) _calculateVar2 = staticmethod(calculateVarG) _calculateVar3 = staticmethod(calculateVarG) _sig1 = 'sig_k' _sig2 = 'sig_sn (per component)' _sig3 = 'sig_sn (per component)'
[docs] def __init__(self, config=None, *, logger=None, **kwargs): super().__init__(config, logger=logger, **kwargs) shape = self.data_shape # z0,1 holds gamma_0 # z2,3 holds gamma_2 self._z[0:4] = [np.zeros(shape, dtype=float) for _ in range(4)] self.logger.debug('Finished building KGGCorr')
@property def gam0(self): return self._z[0] + 1j * self._z[1] @property def gam1(self): return self._z[0] + 1j * self._z[1] @property def gam2(self): return self._z[2] + 1j * self._z[3] @property def gam3(self): return self._z[2] - 1j * self._z[3] @property def gam0r(self): return self._z[0] @property def gam0i(self): return self._z[1] @property def gam1r(self): return self._z[0] @property def gam1i(self): return self._z[1] @property def gam2r(self): return self._z[2] @property def gam2i(self): return self._z[3] @property def gam3r(self): return self._z[2] @property def gam3i(self): return -self._z[3]
[docs] def finalize(self, vark, varg1, varg2): """Finalize the calculation of the correlation function. Parameters: vark (float): The variance of the scalar field. varg1 (float): The variance per component of the first shear field. varg2 (float): The variance per component of the second shear field. """ self._finalize() self._var_num = 2 * vark * varg1 * varg2 if self.bin_type in ['LogSAS', 'LogMultipole']: self._var_num *= 2
@property def vargam0(self): if self._varzeta is None: self._calculate_varzeta(2) return self._varzeta[0] @property def vargam1(self): return self.vargam0 @property def vargam2(self): if self._varzeta is None: self._calculate_varzeta(2) return self._varzeta[1] @property def vargam3(self): return self.vargam2
[docs] def getStat(self): """The standard statistic for the current correlation object as a 1-d array. In this case, the concatenation of gam0.ravel() and gam2.ravel(). """ return np.concatenate([self.gam0.ravel(), self.gam2.ravel()])
[docs] def getWeight(self): """The weight array for the current correlation object as a 1-d array. In this case, 2 copies of self.weight.ravel(). """ return np.concatenate([np.abs(self.weight.ravel())] * 2)
[docs] def write(self, file_name, *, file_type=None, precision=None, write_patch_results=False, write_cov=False): super().write(file_name, file_type=file_type, precision=precision, write_patch_results=write_patch_results, write_cov=write_cov)
write.__doc__ = Corr3.write.__doc__.format( r""" gam0r The real part of the estimator of :math:`\Gamma_0` gam0i The imag part of the estimator of :math:`\Gamma_0` gam2r The real part of the estimator of :math:`\Gamma_2` gam2i The imag part of the estimator of :math:`\Gamma_2` sigma_gam0 The sqrt of the variance estimate of :math:`\Gamma_0` sigma_gam2 The sqrt of the variance estimate of :math:`\Gamma_2` """) @property def _write_class_col_names(self): return ['gam0r', 'gam0i', 'gam2r', 'gam2i', 'sigma_gam0', 'sigma_gam2'] @property def _write_class_data(self): return [self.gam0r, self.gam0i, self.gam2r, self.gam2i, np.sqrt(self.vargam0), np.sqrt(self.vargam2)] def _read_from_data(self, data, params): super()._read_from_data(data, params) s = self.data_shape self._z[0] = data['gam0r'].reshape(s) self._z[1] = data['gam0i'].reshape(s) self._z[2] = data['gam2r'].reshape(s) self._z[3] = data['gam2i'].reshape(s) vargam0 = data['sigma_gam0'].reshape(s)**2 vargam2 = data['sigma_gam2'].reshape(s)**2 self._varzeta = [vargam0, vargam2]
[docs]class GKGCorrelation(Corr3): r"""This class handles the calculation and storage of a 3-point shear-scalar-shear correlation function. With this class, point 2 of the triangle (i.e. the vertex opposite d2) is the one with the shear value. Use `KGGCorrelation` and `GGKCorrelation` for classes with the shear in the other two positions. For the shear projection, we follow the lead of the 3-point shear-shear-shear correlation functions (see `GGGCorrelation` for details), which involves projecting the shear values at each vertex relative to the direction to the triangle's centroid. Furthermore, the GGG correlations have 4 relevant complex values for each triangle: .. math:: \Gamma_0 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2}) \gamma(\mathbf{x3}) \rangle \\ \Gamma_1 &= \langle \gamma(\mathbf{x1})^* \gamma(\mathbf{x2}) \gamma(\mathbf{x3}) \rangle \\ \Gamma_2 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2})^* \gamma(\mathbf{x3}) \rangle \\ \Gamma_3 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2}) \gamma(\mathbf{x3}^*) \rangle \\ With a scalar value at vertex 2, :math:`\Gamma_0 = \Gamma_2` and :math:`\Gamma_1 = \Gamma_3^*`. So there are only two independent values. However, you may access these values using whichever names you find most convenient: ``gam0``, ``gam1``, ``gam2`` and ``gam3`` are all valid attributes, which return the corresponding value. See the doc string of `Corr3` for a description of how the triangles are binned along with the attributes related to the different binning options. In addition to the attributes common to all `Corr3` subclasses, objects of this class hold the following attributes: Attributes: gam0: The 0th "natural" correlation function, :math:`\Gamma_0`. gam1: The 1st "natural" correlation function, :math:`\Gamma_1`. gam2: The 2nd "natural" correlation function, :math:`\Gamma_2`. gam3: The 3rd "natural" correlation function, :math:`\Gamma_3`. vargam0: The variance estimate of :math:`\Gamma_0`, only including the shot noise. vargam1: The variance estimate of :math:`\Gamma_1`, only including the shot noise. vargam2: The variance estimate of :math:`\Gamma_2`, only including the shot noise. vargam3: The variance estimate of :math:`\Gamma_3`, only including the shot noise. The typical usage pattern is as follows:: >>> gkg = treecorr.GKGCorrelation(config) >>> gkg.process(cat1, cat2, cat1) # Compute cross-correlation of two fields. >>> gkg.process(cat1, cat2, cat3) # Compute cross-correlation of three fields. >>> gkg.write(file_name) # Write out to a file. >>> gam0 = gkg.gam0, etc. # Access gamma values directly. >>> gam0r = gkg.gam0r # Or access real and imag parts separately. >>> gam0i = gkg.gam0i Parameters: config (dict): A configuration dict that can be used to pass in kwargs if desired. This dict is allowed to have addition entries besides those listed in `Corr3`, which are ignored here. (default: None) logger: If desired, a logger object for logging. (default: None, in which case one will be built according to the config dict's verbose level.) Keyword Arguments: **kwargs: See the documentation for `Corr3` for the list of allowed keyword arguments, which may be passed either directly or in the config dict. """ _cls = 'GKGCorrelation' _letter1 = 'G' _letter2 = 'K' _letter3 = 'G' _letters = 'GKG' _builder = _treecorr.GKGCorr _calculateVar1 = staticmethod(calculateVarG) _calculateVar2 = staticmethod(calculateVarK) _calculateVar3 = staticmethod(calculateVarG) _sig1 = 'sig_sn (per component)' _sig2 = 'sig_k' _sig3 = 'sig_sn (per component)'
[docs] def __init__(self, config=None, *, logger=None, **kwargs): super().__init__(config, logger=logger, **kwargs) shape = self.data_shape self._z[0:4] = [np.zeros(shape, dtype=float) for _ in range(4)] self.logger.debug('Finished building GKGCorr')
@property def gam0(self): return self._z[0] + 1j * self._z[1] @property def gam1(self): return self._z[2] + 1j * self._z[3] @property def gam2(self): return self._z[0] + 1j * self._z[1] @property def gam3(self): return self._z[2] - 1j * self._z[3] @property def gam0r(self): return self._z[0] @property def gam0i(self): return self._z[1] @property def gam1r(self): return self._z[2] @property def gam1i(self): return self._z[3] @property def gam2r(self): return self._z[0] @property def gam2i(self): return self._z[1] @property def gam3r(self): return self._z[2] @property def gam3i(self): return -self._z[3]
[docs] def finalize(self, varg1, vark, varg2): """Finalize the calculation of the correlation function. Parameters: varg1 (float): The variance per component of the first shear field. vark (float): The variance of the scalar field. varg2 (float): The variance per component of the second shear field. """ self._finalize() self._var_num = 2 * varg1 * vark * varg2 if self.bin_type in ['LogSAS', 'LogMultipole']: self._var_num *= 2
@property def vargam0(self): if self._varzeta is None: self._calculate_varzeta(2) return self._varzeta[0] @property def vargam1(self): if self._varzeta is None: self._calculate_varzeta(2) return self._varzeta[1] @property def vargam2(self): return self.vargam0 @property def vargam3(self): return self.vargam1
[docs] def getStat(self): """The standard statistic for the current correlation object as a 1-d array. In this case, the concatenation of gam0.ravel() and gam1.ravel(). """ return np.concatenate([self.gam0.ravel(), self.gam1.ravel()])
[docs] def getWeight(self): """The weight array for the current correlation object as a 1-d array. In this case, 2 copies of self.weight.ravel(). """ return np.concatenate([np.abs(self.weight.ravel())] * 2)
[docs] def write(self, file_name, *, file_type=None, precision=None, write_patch_results=False, write_cov=False): super().write(file_name, file_type=file_type, precision=precision, write_patch_results=write_patch_results, write_cov=write_cov)
write.__doc__ = Corr3.write.__doc__.format( r""" gam0r The real part of the estimator of :math:`\Gamma_0` gam0i The imag part of the estimator of :math:`\Gamma_0` gam1r The real part of the estimator of :math:`\Gamma_1` gam1i The imag part of the estimator of :math:`\Gamma_1` sigma_gam0 The sqrt of the variance estimate of :math:`\Gamma_0` sigma_gam1 The sqrt of the variance estimate of :math:`\Gamma_1` """) @property def _write_class_col_names(self): return ['gam0r', 'gam0i', 'gam1r', 'gam1i', 'sigma_gam0', 'sigma_gam1'] @property def _write_class_data(self): return [self.gam0r, self.gam0i, self.gam1r, self.gam1i, np.sqrt(self.vargam0), np.sqrt(self.vargam1)] def _read_from_data(self, data, params): super()._read_from_data(data, params) s = self.data_shape self._z[0] = data['gam0r'].reshape(s) self._z[1] = data['gam0i'].reshape(s) self._z[2] = data['gam1r'].reshape(s) self._z[3] = data['gam1i'].reshape(s) vargam0 = data['sigma_gam0'].reshape(s)**2 vargam1 = data['sigma_gam1'].reshape(s)**2 self._varzeta = [vargam0, vargam1]
[docs]class GGKCorrelation(Corr3): r"""This class handles the calculation and storage of a 3-point shear-shear-scalar correlation function. With this class, point 1 of the triangle (i.e. the vertex opposite d1) is the one with the shear value. Use `GKGCorrelation` and `KGGCorrelation` for classes with the shear in the other two positions. For the shear projection, we follow the lead of the 3-point shear-shear-shear correlation functions (see `GGGCorrelation` for details), which involves projecting the shear values at each vertex relative to the direction to the triangle's centroid. Furthermore, the GGG correlations have 4 relevant complex values for each triangle: .. math:: \Gamma_0 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2}) \gamma(\mathbf{x3}) \rangle \\ \Gamma_1 &= \langle \gamma(\mathbf{x1})^* \gamma(\mathbf{x2}) \gamma(\mathbf{x3}) \rangle \\ \Gamma_2 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2})^* \gamma(\mathbf{x3}) \rangle \\ \Gamma_3 &= \langle \gamma(\mathbf{x1}) \gamma(\mathbf{x2}) \gamma(\mathbf{x3}^*) \rangle \\ With a scalar value at vertex 3, :math:`\Gamma_0 = \Gamma_3` and :math:`\Gamma_1 = \Gamma_2^*`. So there are only two independent values. However, you may access these values using whichever names you find most convenient: ``gam0``, ``gam1``, ``gam2`` and ``gam3`` are all valid attributes, which return the corresponding value. See the doc string of `Corr3` for a description of how the triangles are binned along with the attributes related to the different binning options. In addition to the attributes common to all `Corr3` subclasses, objects of this class hold the following attributes: Attributes: gam0: The 0th "natural" correlation function, :math:`\Gamma_0`. gam1: The 1st "natural" correlation function, :math:`\Gamma_1`. gam2: The 2nd "natural" correlation function, :math:`\Gamma_2`. gam3: The 3rd "natural" correlation function, :math:`\Gamma_3`. vargam0: The variance estimate of :math:`\Gamma_0`, only including the shot noise. vargam1: The variance estimate of :math:`\Gamma_1`, only including the shot noise. vargam2: The variance estimate of :math:`\Gamma_2`, only including the shot noise. vargam3: The variance estimate of :math:`\Gamma_3`, only including the shot noise. The typical usage pattern is as follows:: >>> ggk = treecorr.GGKCorrelation(config) >>> ggk.process(cat1, cat2) # Compute cross-correlation of two fields. >>> ggk.process(cat1, cat2, cat3) # Compute cross-correlation of three fields. >>> ggk.write(file_name) # Write out to a file. >>> gam0 = ggk.gam0, etc. # Access gamma values directly. >>> gam0r = ggk.gam0r # Or access real and imag parts separately. >>> gam0i = ggk.gam0i Parameters: config (dict): A configuration dict that can be used to pass in kwargs if desired. This dict is allowed to have addition entries besides those listed in `Corr3`, which are ignored here. (default: None) logger: If desired, a logger object for logging. (default: None, in which case one will be built according to the config dict's verbose level.) Keyword Arguments: **kwargs: See the documentation for `Corr3` for the list of allowed keyword arguments, which may be passed either directly or in the config dict. """ _cls = 'GGKCorrelation' _letter1 = 'G' _letter2 = 'G' _letter3 = 'K' _letters = 'GGK' _builder = _treecorr.GGKCorr _calculateVar1 = staticmethod(calculateVarG) _calculateVar2 = staticmethod(calculateVarG) _calculateVar3 = staticmethod(calculateVarK) _sig1 = 'sig_sn (per component)' _sig2 = 'sig_sn (per component)' _sig3 = 'sig_k'
[docs] def __init__(self, config=None, *, logger=None, **kwargs): super().__init__(config, logger=logger, **kwargs) shape = self.data_shape self._z[0:4] = [np.zeros(shape, dtype=float) for _ in range(4)] self.logger.debug('Finished building GGKCorr')
@property def gam0(self): return self._z[0] + 1j * self._z[1] @property def gam1(self): return self._z[2] + 1j * self._z[3] @property def gam2(self): return self._z[2] - 1j * self._z[3] @property def gam3(self): return self._z[0] + 1j * self._z[1] @property def gam0r(self): return self._z[0] @property def gam0i(self): return self._z[1] @property def gam1r(self): return self._z[2] @property def gam1i(self): return self._z[3] @property def gam2r(self): return self._z[2] @property def gam2i(self): return -self._z[3] @property def gam3r(self): return self._z[0] @property def gam3i(self): return self._z[1]
[docs] def finalize(self, varg1, varg2, vark): """Finalize the calculation of the correlation function. Parameters: varg1 (float): The variance per component of the first shear field. varg2 (float): The variance per component of the second shear field. vark (float): The variance of the scalar field. """ self._finalize() self._var_num = 2 * varg1 * varg2 * vark if self.bin_type in ['LogSAS', 'LogMultipole']: self._var_num *= 2
@property def vargam0(self): if self._varzeta is None: self._calculate_varzeta(2) return self._varzeta[0] @property def vargam1(self): if self._varzeta is None: self._calculate_varzeta(2) return self._varzeta[1] @property def vargam2(self): return self.vargam1 @property def vargam3(self): return self.vargam0
[docs] def getStat(self): """The standard statistic for the current correlation object as a 1-d array. In this case, the concatenation of gam0.ravel() and gam1.ravel(). """ return np.concatenate([self.gam0.ravel(), self.gam1.ravel()])
[docs] def getWeight(self): """The weight array for the current correlation object as a 1-d array. In this case, 2 copies of self.weight.ravel(). """ return np.concatenate([np.abs(self.weight.ravel())] * 2)
[docs] def write(self, file_name, *, file_type=None, precision=None, write_patch_results=False, write_cov=False): super().write(file_name, file_type=file_type, precision=precision, write_patch_results=write_patch_results, write_cov=write_cov)
write.__doc__ = Corr3.write.__doc__.format( r""" gam0r The real part of the estimator of :math:`\Gamma_0` gam0i The imag part of the estimator of :math:`\Gamma_0` gam1r The real part of the estimator of :math:`\Gamma_1` gam1i The imag part of the estimator of :math:`\Gamma_1` sigma_gam0 The sqrt of the variance estimate of :math:`\Gamma_0` sigma_gam1 The sqrt of the variance estimate of :math:`\Gamma_1` """) @property def _write_class_col_names(self): return ['gam0r', 'gam0i', 'gam1r', 'gam1i', 'sigma_gam0', 'sigma_gam1'] @property def _write_class_data(self): return [self.gam0r, self.gam0i, self.gam1r, self.gam1i, np.sqrt(self.vargam0), np.sqrt(self.vargam1)] def _read_from_data(self, data, params): super()._read_from_data(data, params) s = self.data_shape self._z[0] = data['gam0r'].reshape(s) self._z[1] = data['gam0i'].reshape(s) self._z[2] = data['gam1r'].reshape(s) self._z[3] = data['gam1i'].reshape(s) vargam0 = data['sigma_gam0'].reshape(s)**2 vargam1 = data['sigma_gam1'].reshape(s)**2 self._varzeta = [vargam0, vargam1]