Esempio n. 1
0
 def compute_3pt_pix(self):
     kkk = treecorr.KKKCorrelation(config=self.config_3pt)
     toc = time.time()
     kkk.process(self.cat)
     tic = time.time()
     print '3PCF took', tic - toc
     stdout.flush()
     self.kkk = kkk
Esempio n. 2
0
def test_constant():
    # A fairly trivial test is to use a constant value of kappa everywhere.

    ngal = 500
    A = 0.05
    L = 100.
    rng = np.random.RandomState(8675309)
    x = (rng.random_sample(ngal) - 0.5) * L
    y = (rng.random_sample(ngal) - 0.5) * L
    kappa = A * np.ones(ngal)

    cat = treecorr.Catalog(x=x,
                           y=y,
                           k=kappa,
                           x_units='arcmin',
                           y_units='arcmin')

    min_sep = 10.
    max_sep = 25.
    nbins = 5
    min_u = 0.6
    max_u = 0.9
    nubins = 3
    min_v = 0.5
    max_v = 0.9
    nvbins = 5
    kkk = treecorr.KKKCorrelation(min_sep=min_sep,
                                  max_sep=max_sep,
                                  nbins=nbins,
                                  min_u=min_u,
                                  max_u=max_u,
                                  min_v=min_v,
                                  max_v=max_v,
                                  nubins=nubins,
                                  nvbins=nvbins,
                                  sep_units='arcmin',
                                  verbose=1)
    kkk.process(cat)
    print('kkk.zeta = ', kkk.zeta.flatten())
    np.testing.assert_allclose(kkk.zeta, A**3, rtol=1.e-5)

    # Should also work as a cross-correlation
    kkk.process(cat, cat, cat)
    print('as cross-correlation: kkk.zeta = ', kkk.zeta.flatten())
    np.testing.assert_allclose(kkk.zeta, A**3, rtol=1.e-5)

    # Now add some noise to the values. It should still work, but at slightly lower accuracy.
    kappa += 0.001 * (rng.random_sample(ngal) - 0.5)
    cat = treecorr.Catalog(x=x,
                           y=y,
                           k=kappa,
                           x_units='arcmin',
                           y_units='arcmin')
    kkk.process(cat)
    print('with noise: kkk.zeta = ', kkk.zeta.flatten())
    np.testing.assert_allclose(kkk.zeta, A**3, rtol=3.e-3)
Esempio n. 3
0
    def __init__(self, dataname, runname, sample_type, n_jackknife):
        self.sample_type = sample_type  #redmagicHD, dark_matter
        self.dataname = dataname
        self.runname = runname
        config_fname = output_path + self.runname + '.config'
        try:
            with open(config_fname) as f:
                self.configdict = yaml.load(f.read())
        except IOError:
            print 'config file ' + config_fname + ' not found.'
            raise

        self.kk = treecorr.KKCorrelation(config=self.configdict['2PCF'])
        self.kkk = treecorr.KKKCorrelation(config=self.configdict['3PCF'])

        self.n_jackknife = n_jackknife

        self.zetas = []
        self.weights = []
        self.xis = []
Esempio n. 4
0
def corr3(config, logger=None):
    """Run the full three-point correlation function code based on the parameters in the
    given config dict.

    The function print_corr3_params() will output information about the valid parameters
    that are expected to be in the config dict.

    Optionally a logger parameter maybe given, in which case it is used for logging.
    If not given, the logging will be based on the verbose and log_file parameters.

    :param config:  The configuration dict which defines what to do.
    :param 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.)
    """
    # Setup logger based on config verbose value
    if logger is None:
        logger = treecorr.config.setup_logger(
            treecorr.config.get(config, 'verbose', int, 1),
            config.get('log_file', None))

    # Check that config doesn't have any extra parameters.
    # (Such values are probably typos.)
    # Also convert the given parameters to the correct type, etc.
    config = treecorr.config.check_config(config, corr3_valid_params,
                                          corr3_aliases, logger)

    import pprint
    logger.debug('Using configuration dict:\n%s', pprint.pformat(config))

    if ('output_dots' not in config and config.get('log_file', None) is None
            and config['verbose'] >= 2):
        config['output_dots'] = True

    # Set the number of threads
    num_threads = config.get('num_threads', None)
    logger.debug('From config dict, num_threads = %s', num_threads)
    treecorr.set_omp_threads(num_threads, logger)

    # Read in the input files.  Each of these is a list.
    cat1 = treecorr.read_catalogs(config, 'file_name', 'file_list', 0, logger)
    if len(cat1) == 0:
        raise AttributeError("Either file_name or file_list is required")
    cat2 = treecorr.read_catalogs(config, 'file_name2', 'rand_file_list2', 1,
                                  logger)
    cat3 = treecorr.read_catalogs(config, 'file_name3', 'rand_file_list3', 1,
                                  logger)
    rand1 = treecorr.read_catalogs(config, 'rand_file_name', 'rand_file_list',
                                   0, logger)
    rand2 = treecorr.read_catalogs(config, 'rand_file_name2',
                                   'rand_file_list2', 1, logger)
    rand3 = treecorr.read_catalogs(config, 'rand_file_name3',
                                   'rand_file_list3', 1, logger)
    if len(cat2) == 0 and len(rand2) > 0:
        raise AttributeError("rand_file_name2 is invalid without file_name2")
    if len(cat3) == 0 and len(rand3) > 0:
        raise AttributeError("rand_file_name3 is invalid without file_name3")
    logger.info("Done reading input catalogs")

    # Do GGG correlation function if necessary
    if 'ggg_file_name' in config:  #or 'm3_file_name' in config:
        logger.info("Start GGG calculations...")
        ggg = treecorr.GGGCorrelation(config, logger)
        ggg.process(cat1, cat2, cat3)
        logger.info("Done GGG calculations.")
        if 'ggg_file_name' in config:
            ggg.write(config['ggg_file_name'])
        if 'm3_file_name' in config:
            ggg.writeMapSq(config['m3_file_name'])

    # Do NNN correlation function if necessary
    if 'nnn_file_name' in config:
        if len(rand1) == 0:
            raise AttributeError(
                "rand_file_name is required for NNN correlation")
        if len(cat2) > 0 and len(rand2) == 0:
            raise AttributeError(
                "rand_file_name2 is required for NNN cross-correlation")
        if len(cat3) > 0 and len(rand3) == 0:
            raise AttributeError(
                "rand_file_name3 is required for NNN cross-correlation")
        if (len(cat2) > 0) != (len(cat3) > 0):
            raise NotImplementedError(
                "Cannot yet handle 3-point corrleations with only two catalogs. "
                + "Need both cat2 and cat3.")
        logger.info("Start DDD calculations...")
        ddd = treecorr.NNNCorrelation(config, logger)
        ddd.process(cat1, cat2, cat3)
        logger.info("Done DDD calculations.")

        if len(cat2) == 0:
            rrr = treecorr.NNNCorrelation(config, logger)
            rrr.process(rand1)
            logger.info("Done RRR calculations.")

            # For the next step, just make cat2 = cat3 = cat1 and rand2 = rand3 = rand1.
            cat2 = cat3 = cat1
            rand2 = rand3 = rand1
        else:
            rrr = treecorr.NNNCorrelation(config, logger)
            rrr.process(rand1, rand2, rand3)
            logger.info("Done RRR calculations.")

        if config['nnn_statistic'] == 'compensated':
            drr = treecorr.NNNCorrelation(config, logger)
            drr.process(cat1, rand2, rand3)
            logger.info("Done DRR calculations.")
            ddr = treecorr.NNNCorrelation(config, logger)
            ddr.process(cat1, cat2, rand3)
            logger.info("Done DDR calculations.")
            rdr = treecorr.NNNCorrelation(config, logger)
            rdr.process(rand1, cat2, rand3)
            logger.info("Done RDR calculations.")
            rrd = treecorr.NNNCorrelation(config, logger)
            rrd.process(rand1, rand2, cat3)
            logger.info("Done RRD calculations.")
            drd = treecorr.NNNCorrelation(config, logger)
            drd.process(cat1, rand2, cat3)
            logger.info("Done DRD calculations.")
            rdd = treecorr.NNNCorrelation(config, logger)
            rdd.process(rand1, cat2, cat3)
            logger.info("Done RDD calculations.")
            ddd.write(config['nnn_file_name'], rrr, drr, rdr, rrd, ddr, drd,
                      rdd)
        else:
            ddd.write(config['nnn_file_name'], rrr)

    # Do KKK correlation function if necessary
    if 'kkk_file_name' in config:
        logger.info("Start KKK calculations...")
        kkk = treecorr.KKKCorrelation(config, logger)
        kkk.process(cat1, cat2, cat3)
        logger.info("Done KKK calculations.")
        kkk.write(config['kkk_file_name'])

    # Do NNG correlation function if necessary
    if False:
        #if 'nng_file_name' in config or 'nnm_file_name' in config:
        if len(cat3) == 0:
            raise AttributeError("file_name3 is required for nng correlation")
        logger.info("Start NNG calculations...")
        nng = treecorr.NNGCorrelation(config, logger)
        nng.process(cat1, cat2, cat3)
        logger.info("Done NNG calculation.")

        # The default ng_statistic is compensated _iff_ rand files are given.
        rrg = None
        if len(rand1) == 0:
            if config.get('nng_statistic', None) == 'compensated':
                raise AttributeError(
                    "rand_files is required for nng_statistic = compensated")
        elif config.get('nng_statistic', 'compensated') == 'compensated':
            rrg = treecorr.NNGCorrelation(config, logger)
            rrg.process(rand1, rand1, cat2)
            logger.info("Done RRG calculation.")

        if 'nng_file_name' in config:
            nng.write(config['nng_file_name'], rrg)
        if 'nnm_file_name' in config:
            nng.writeNNMap(config['nnm_file_name'], rrg)

    # Do NNK correlation function if necessary
    if False:
        #if 'nnk_file_name' in config:
        if len(cat3) == 0:
            raise AttributeError("file_name3 is required for nnk correlation")
        logger.info("Start NNK calculations...")
        nnk = treecorr.NNKCorrelation(config, logger)
        nnk.process(cat1, cat2, cat3)
        logger.info("Done NNK calculation.")

        rrk = None
        if len(rand1) == 0:
            if config.get('nnk_statistic', None) == 'compensated':
                raise AttributeError(
                    "rand_files is required for nnk_statistic = compensated")
        elif config.get('nnk_statistic', 'compensated') == 'compensated':
            rrk = treecorr.NNKCorrelation(config, logger)
            rrk.process(rand1, rand1, cat2)
            logger.info("Done RRK calculation.")

        nnk.write(config['nnk_file_name'], rrk)

    # Do KKG correlation function if necessary
    if False:
        #if 'kkg_file_name' in config:
        if len(cat3) == 0:
            raise AttributeError("file_name3 is required for kkg correlation")
        logger.info("Start KKG calculations...")
        kkg = treecorr.KKGCorrelation(config, logger)
        kkg.process(cat1, cat2, cat3)
        logger.info("Done KKG calculation.")
        kkg.write(config['kkg_file_name'])
Esempio n. 5
0
def test_kkk():
    # Use kappa(r) = A exp(-r^2/2s^2)
    #
    # The Fourier transform is: kappa~(k) = 2 pi A s^2 exp(-s^2 k^2/2) / L^2
    #
    # B(k1,k2) = <k~(k1) k~(k2) k~(-k1-k2)>
    #          = (2 pi A (s/L)^2)^3 exp(-s^2 (|k1|^2 + |k2|^2 - k1.k2))
    #          = (2 pi A (s/L)^2)^3 exp(-s^2 (|k1|^2 + |k2|^2 + |k3|^2)/2)
    #
    # zeta(r1,r2) = (1/2pi)^4 int(d^2k1 int(d^2k2 exp(ik1.x1) exp(ik2.x2) B(k1,k2) ))
    #             = 2/3 pi A^3 (s/L)^2 exp(-(x1^2 + y1^2 + x2^2 + y2^2 - x1x2 - y1y2)/3s^2)
    #             = 2/3 pi A^3 (s/L)^2 exp(-(d1^2 + d2^2 + d3^2)/6s^2)

    A = 0.05
    s = 10.
    if __name__ == '__main__':
        ngal = 200000
        L = 30. * s  # Not infinity, so this introduces some error.  Our integrals were to infinity.
        tol_factor = 1
    else:
        # Looser tests from nosetests that don't take so long to run.
        ngal = 10000
        L = 20. * s
        tol_factor = 5
    rng = np.random.RandomState(8675309)
    x = (rng.random_sample(ngal) - 0.5) * L
    y = (rng.random_sample(ngal) - 0.5) * L
    r2 = (x**2 + y**2) / s**2
    kappa = A * np.exp(-r2 / 2.)

    min_sep = 11.
    max_sep = 15.
    nbins = 3
    min_u = 0.7
    max_u = 1.0
    nubins = 3
    min_v = 0.1
    max_v = 0.3
    nvbins = 2

    cat = treecorr.Catalog(x=x,
                           y=y,
                           k=kappa,
                           x_units='arcmin',
                           y_units='arcmin')
    kkk = treecorr.KKKCorrelation(min_sep=min_sep,
                                  max_sep=max_sep,
                                  nbins=nbins,
                                  min_u=min_u,
                                  max_u=max_u,
                                  min_v=min_v,
                                  max_v=max_v,
                                  nubins=nubins,
                                  nvbins=nvbins,
                                  sep_units='arcmin',
                                  verbose=1)
    kkk.process(cat)

    # log(<d>) != <logd>, but it should be close:
    print('meanlogd1 - log(meand1) = ', kkk.meanlogd1 - np.log(kkk.meand1))
    print('meanlogd2 - log(meand2) = ', kkk.meanlogd2 - np.log(kkk.meand2))
    print('meanlogd3 - log(meand3) = ', kkk.meanlogd3 - np.log(kkk.meand3))
    print('meand3 / meand2 = ', kkk.meand3 / kkk.meand2)
    print('meanu = ', kkk.meanu)
    print('max diff = ', np.max(np.abs(kkk.meand3 / kkk.meand2 - kkk.meanu)))
    print('max rel diff = ',
          np.max(np.abs((kkk.meand3 / kkk.meand2 - kkk.meanu) / kkk.meanu)))
    print('(meand1 - meand2)/meand3 = ',
          (kkk.meand1 - kkk.meand2) / kkk.meand3)
    print('meanv = ', kkk.meanv)
    print(
        'max diff = ',
        np.max(
            np.abs((kkk.meand1 - kkk.meand2) / kkk.meand3 -
                   np.abs(kkk.meanv))))
    print(
        'max rel diff = ',
        np.max(
            np.abs(
                ((kkk.meand1 - kkk.meand2) / kkk.meand3 - np.abs(kkk.meanv)) /
                kkk.meanv)))
    np.testing.assert_allclose(kkk.meanlogd1, np.log(kkk.meand1), rtol=1.e-3)
    np.testing.assert_allclose(kkk.meanlogd2, np.log(kkk.meand2), rtol=1.e-3)
    np.testing.assert_allclose(kkk.meanlogd3, np.log(kkk.meand3), rtol=1.e-3)
    np.testing.assert_allclose(kkk.meand3 / kkk.meand2,
                               kkk.meanu,
                               rtol=1.e-5 * tol_factor)
    np.testing.assert_allclose(np.abs(kkk.meand1 - kkk.meand2) / kkk.meand3,
                               np.abs(kkk.meanv),
                               rtol=1.e-5 * tol_factor,
                               atol=1.e-5 * tol_factor)
    np.testing.assert_allclose(kkk.meanlogd3 - kkk.meanlogd2,
                               np.log(kkk.meanu),
                               atol=1.e-3 * tol_factor)
    np.testing.assert_allclose(np.log(np.abs(kkk.meand1 - kkk.meand2)) -
                               kkk.meanlogd3,
                               np.log(np.abs(kkk.meanv)),
                               atol=2.e-3 * tol_factor)

    d1 = kkk.meand1
    d2 = kkk.meand2
    d3 = kkk.meand3
    #print('rnom = ',np.exp(kkk.logr))
    #print('unom = ',kkk.u)
    #print('vnom = ',kkk.v)
    #print('d1 = ',d1)
    #print('d2 = ',d2)
    #print('d3 = ',d3)
    # The L^2 term in the denominator of true_zeta is the area over which the integral is done.
    # Since the centers of the triangles don't go to the edge of the box, we approximate the
    # correct area by subtracting off 2d2 from L, which should give a slightly better estimate
    # of the correct area to use here.
    L = L - 2. * d2
    true_zeta = (2. * np.pi / 3) * A**3 * (s / L)**2 * np.exp(
        -(d1**2 + d2**2 + d3**2) / (6. * s**2))

    #print('ntri = ',kkk.ntri)
    print('zeta = ', kkk.zeta)
    print('true_zeta = ', true_zeta)
    #print('ratio = ',kkk.zeta / true_zeta)
    #print('diff = ',kkk.zeta - true_zeta)
    print('max rel diff = ', np.max(np.abs(
        (kkk.zeta - true_zeta) / true_zeta)))
    np.testing.assert_allclose(kkk.zeta, true_zeta, rtol=0.1 * tol_factor)
    np.testing.assert_allclose(np.log(np.abs(kkk.zeta)),
                               np.log(np.abs(true_zeta)),
                               atol=0.1 * tol_factor)

    # Check that we get the same result using the corr3 functin:
    cat.write(os.path.join('data', 'kkk_data.dat'))
    config = treecorr.config.read_config('configs/kkk.yaml')
    config['verbose'] = 0
    treecorr.corr3(config)
    corr3_output = np.genfromtxt(os.path.join('output', 'kkk.out'),
                                 names=True,
                                 skip_header=1)
    np.testing.assert_almost_equal(corr3_output['zeta'], kkk.zeta.flatten())

    try:
        import fitsio
    except ImportError:
        print('Skipping FITS tests, since fitsio is not installed')
        return

    # Check the fits write option
    out_file_name = os.path.join('output', 'kkk_out.fits')
    kkk.write(out_file_name)
    data = fitsio.read(out_file_name)
    np.testing.assert_almost_equal(data['r_nom'], np.exp(kkk.logr).flatten())
    np.testing.assert_almost_equal(data['u_nom'], kkk.u.flatten())
    np.testing.assert_almost_equal(data['v_nom'], kkk.v.flatten())
    np.testing.assert_almost_equal(data['meand1'], kkk.meand1.flatten())
    np.testing.assert_almost_equal(data['meanlogd1'], kkk.meanlogd1.flatten())
    np.testing.assert_almost_equal(data['meand2'], kkk.meand2.flatten())
    np.testing.assert_almost_equal(data['meanlogd2'], kkk.meanlogd2.flatten())
    np.testing.assert_almost_equal(data['meand3'], kkk.meand3.flatten())
    np.testing.assert_almost_equal(data['meanlogd3'], kkk.meanlogd3.flatten())
    np.testing.assert_almost_equal(data['meanu'], kkk.meanu.flatten())
    np.testing.assert_almost_equal(data['meanv'], kkk.meanv.flatten())
    np.testing.assert_almost_equal(data['zeta'], kkk.zeta.flatten())
    np.testing.assert_almost_equal(data['sigma_zeta'],
                                   np.sqrt(kkk.varzeta.flatten()))
    np.testing.assert_almost_equal(data['weight'], kkk.weight.flatten())
    np.testing.assert_almost_equal(data['ntri'], kkk.ntri.flatten())

    # Check the read function
    # Note: These don't need the flatten. The read function should reshape them to the right shape.
    kkk2 = treecorr.KKKCorrelation(min_sep=min_sep,
                                   max_sep=max_sep,
                                   nbins=nbins,
                                   min_u=min_u,
                                   max_u=max_u,
                                   min_v=min_v,
                                   max_v=max_v,
                                   nubins=nubins,
                                   nvbins=nvbins,
                                   sep_units='arcmin',
                                   verbose=1)
    kkk2.read(out_file_name)
    np.testing.assert_almost_equal(kkk2.logr, kkk.logr)
    np.testing.assert_almost_equal(kkk2.u, kkk.u)
    np.testing.assert_almost_equal(kkk2.v, kkk.v)
    np.testing.assert_almost_equal(kkk2.meand1, kkk.meand1)
    np.testing.assert_almost_equal(kkk2.meanlogd1, kkk.meanlogd1)
    np.testing.assert_almost_equal(kkk2.meand2, kkk.meand2)
    np.testing.assert_almost_equal(kkk2.meanlogd2, kkk.meanlogd2)
    np.testing.assert_almost_equal(kkk2.meand3, kkk.meand3)
    np.testing.assert_almost_equal(kkk2.meanlogd3, kkk.meanlogd3)
    np.testing.assert_almost_equal(kkk2.meanu, kkk.meanu)
    np.testing.assert_almost_equal(kkk2.meanv, kkk.meanv)
    np.testing.assert_almost_equal(kkk2.zeta, kkk.zeta)
    np.testing.assert_almost_equal(kkk2.varzeta, kkk.varzeta)
    np.testing.assert_almost_equal(kkk2.weight, kkk.weight)
    np.testing.assert_almost_equal(kkk2.ntri, kkk.ntri)
    assert kkk2.coords == kkk.coords
    assert kkk2.metric == kkk.metric
    assert kkk2.sep_units == kkk.sep_units
    assert kkk2.bin_type == kkk.bin_type
Esempio n. 6
0
def test_direct_spherical():
    # Repeat in spherical coords

    ngal = 50
    s = 10.
    rng = np.random.RandomState(8675309)
    x = rng.normal(0, s, (ngal, ))
    y = rng.normal(
        0, s,
        (ngal, )) + 200  # Put everything at large y, so small angle on sky
    z = rng.normal(0, s, (ngal, ))
    w = rng.random_sample(ngal)
    kap = rng.normal(0, 3, (ngal, ))
    w = np.ones_like(w)

    ra, dec = coord.CelestialCoord.xyz_to_radec(x, y, z)

    cat = treecorr.Catalog(ra=ra,
                           dec=dec,
                           ra_units='rad',
                           dec_units='rad',
                           w=w,
                           k=kap)

    min_sep = 1.
    bin_size = 0.2
    nrbins = 10
    nubins = 5
    nvbins = 5
    max_sep = min_sep * np.exp(nrbins * bin_size)
    kkk = treecorr.KKKCorrelation(min_sep=min_sep,
                                  bin_size=bin_size,
                                  nbins=nrbins,
                                  sep_units='deg',
                                  brute=True)
    kkk.process(cat)

    r = np.sqrt(x**2 + y**2 + z**2)
    x /= r
    y /= r
    z /= r
    north_pole = coord.CelestialCoord(0 * coord.radians, 90 * coord.degrees)

    true_ntri = np.zeros((nrbins, nubins, 2 * nvbins), dtype=int)
    true_weight = np.zeros((nrbins, nubins, 2 * nvbins), dtype=float)
    true_zeta = np.zeros((nrbins, nubins, 2 * nvbins), dtype=float)

    rad_min_sep = min_sep * coord.degrees / coord.radians
    rad_max_sep = max_sep * coord.degrees / coord.radians
    c = [
        coord.CelestialCoord(r * coord.radians, d * coord.radians)
        for (r, d) in zip(ra, dec)
    ]
    for i in range(ngal):
        for j in range(i + 1, ngal):
            for k in range(j + 1, ngal):
                d12 = np.sqrt((x[i] - x[j])**2 + (y[i] - y[j])**2 +
                              (z[i] - z[j])**2)
                d23 = np.sqrt((x[j] - x[k])**2 + (y[j] - y[k])**2 +
                              (z[j] - z[k])**2)
                d31 = np.sqrt((x[k] - x[i])**2 + (y[k] - y[i])**2 +
                              (z[k] - z[i])**2)

                d3, d2, d1 = sorted([d12, d23, d31])
                rindex = np.floor(np.log(d2 / rad_min_sep) /
                                  bin_size).astype(int)
                if rindex < 0 or rindex >= nrbins: continue

                if [d1, d2, d3] == [d23, d31, d12]: ii, jj, kk = i, j, k
                elif [d1, d2, d3] == [d23, d12, d31]: ii, jj, kk = i, k, j
                elif [d1, d2, d3] == [d31, d12, d23]: ii, jj, kk = j, k, i
                elif [d1, d2, d3] == [d31, d23, d12]: ii, jj, kk = j, i, k
                elif [d1, d2, d3] == [d12, d23, d31]: ii, jj, kk = k, i, j
                elif [d1, d2, d3] == [d12, d31, d23]: ii, jj, kk = k, j, i
                else: assert False
                # Now use ii, jj, kk rather than i,j,k, to get the indices
                # that correspond to the points in the right order.

                u = d3 / d2
                v = (d1 - d2) / d3
                if (((x[jj] - x[ii]) * (y[kk] - y[ii]) - (x[kk] - x[ii]) *
                     (y[jj] - y[ii])) * z[ii] +
                    ((y[jj] - y[ii]) * (z[kk] - z[ii]) - (y[kk] - y[ii]) *
                     (z[jj] - z[ii])) * x[ii] +
                    ((z[jj] - z[ii]) * (x[kk] - x[ii]) - (z[kk] - z[ii]) *
                     (x[jj] - x[ii])) * y[ii]) > 0:
                    v = -v

                uindex = np.floor(u / bin_size).astype(int)
                assert 0 <= uindex < nubins
                vindex = np.floor((v + 1) / bin_size).astype(int)
                assert 0 <= vindex < 2 * nvbins

                www = w[i] * w[j] * w[k]
                zeta = www * kap[i] * kap[j] * kap[k]

                true_ntri[rindex, uindex, vindex] += 1
                true_weight[rindex, uindex, vindex] += www
                true_zeta[rindex, uindex, vindex] += zeta

    pos = true_weight > 0
    true_zeta[pos] /= true_weight[pos]

    np.testing.assert_array_equal(kkk.ntri, true_ntri)
    np.testing.assert_allclose(kkk.weight, true_weight, rtol=1.e-5, atol=1.e-8)
    np.testing.assert_allclose(kkk.zeta, true_zeta, rtol=1.e-4, atol=1.e-6)

    try:
        import fitsio
    except ImportError:
        print('Skipping FITS tests, since fitsio is not installed')
        return

    # Check that running via the corr3 script works correctly.
    config = treecorr.config.read_config('configs/kkk_direct_spherical.yaml')
    cat.write(config['file_name'])
    treecorr.corr3(config)
    data = fitsio.read(config['kkk_file_name'])
    np.testing.assert_allclose(data['r_nom'], kkk.rnom.flatten())
    np.testing.assert_allclose(data['u_nom'], kkk.u.flatten())
    np.testing.assert_allclose(data['v_nom'], kkk.v.flatten())
    np.testing.assert_allclose(data['ntri'], kkk.ntri.flatten())
    np.testing.assert_allclose(data['weight'], kkk.weight.flatten())
    np.testing.assert_allclose(data['zeta'], kkk.zeta.flatten(), rtol=1.e-3)

    # Repeat with binslop = 0
    # And don't do any top-level recursion so we actually test not going to the leaves.
    kkk = treecorr.KKKCorrelation(min_sep=min_sep,
                                  bin_size=bin_size,
                                  nbins=nrbins,
                                  sep_units='deg',
                                  bin_slop=0,
                                  max_top=0)
    kkk.process(cat)
    np.testing.assert_array_equal(kkk.ntri, true_ntri)
    np.testing.assert_allclose(kkk.weight, true_weight, rtol=1.e-5, atol=1.e-8)
    np.testing.assert_allclose(kkk.zeta, true_zeta, rtol=1.e-4, atol=1.e-6)
Esempio n. 7
0
def test_direct():
    # If the catalogs are small enough, we can do a direct calculation to see if comes out right.
    # This should exactly match the treecorr result if brute=True.

    ngal = 100
    s = 10.
    rng = np.random.RandomState(8675309)
    x = rng.normal(0, s, (ngal, ))
    y = rng.normal(0, s, (ngal, ))
    w = rng.random_sample(ngal)
    kap = rng.normal(0, 3, (ngal, ))

    cat = treecorr.Catalog(x=x, y=y, w=w, k=kap)

    min_sep = 1.
    bin_size = 0.2
    nrbins = 10
    nubins = 5
    nvbins = 5
    max_sep = min_sep * np.exp(nrbins * bin_size)
    kkk = treecorr.KKKCorrelation(min_sep=min_sep,
                                  bin_size=bin_size,
                                  nbins=nrbins,
                                  brute=True)
    kkk.process(cat, num_threads=2)

    true_ntri = np.zeros((nrbins, nubins, 2 * nvbins), dtype=int)
    true_weight = np.zeros((nrbins, nubins, 2 * nvbins), dtype=float)
    true_zeta = np.zeros((nrbins, nubins, 2 * nvbins), dtype=float)
    for i in range(ngal):
        for j in range(i + 1, ngal):
            for k in range(j + 1, ngal):
                d12 = np.sqrt((x[i] - x[j])**2 + (y[i] - y[j])**2)
                d23 = np.sqrt((x[j] - x[k])**2 + (y[j] - y[k])**2)
                d31 = np.sqrt((x[k] - x[i])**2 + (y[k] - y[i])**2)

                d3, d2, d1 = sorted([d12, d23, d31])
                rindex = np.floor(np.log(d2 / min_sep) / bin_size).astype(int)
                if rindex < 0 or rindex >= nrbins: continue

                if [d1, d2, d3] == [d23, d31, d12]: ii, jj, kk = i, j, k
                elif [d1, d2, d3] == [d23, d12, d31]: ii, jj, kk = i, k, j
                elif [d1, d2, d3] == [d31, d12, d23]: ii, jj, kk = j, k, i
                elif [d1, d2, d3] == [d31, d23, d12]: ii, jj, kk = j, i, k
                elif [d1, d2, d3] == [d12, d23, d31]: ii, jj, kk = k, i, j
                elif [d1, d2, d3] == [d12, d31, d23]: ii, jj, kk = k, j, i
                else: assert False
                # Now use ii, jj, kk rather than i,j,k, to get the indices
                # that correspond to the points in the right order.

                u = d3 / d2
                v = (d1 - d2) / d3
                if (x[jj] - x[ii]) * (y[kk] - y[ii]) < (x[kk] - x[ii]) * (
                        y[jj] - y[ii]):
                    v = -v

                uindex = np.floor(u / bin_size).astype(int)
                assert 0 <= uindex < nubins
                vindex = np.floor((v + 1) / bin_size).astype(int)
                assert 0 <= vindex < 2 * nvbins

                www = w[i] * w[j] * w[k]
                zeta = www * kap[i] * kap[j] * kap[k]

                true_ntri[rindex, uindex, vindex] += 1
                true_weight[rindex, uindex, vindex] += www
                true_zeta[rindex, uindex, vindex] += zeta

    pos = true_weight > 0
    true_zeta[pos] /= true_weight[pos]

    np.testing.assert_array_equal(kkk.ntri, true_ntri)
    np.testing.assert_allclose(kkk.weight, true_weight, rtol=1.e-5, atol=1.e-8)
    np.testing.assert_allclose(kkk.zeta, true_zeta, rtol=1.e-5, atol=1.e-8)

    try:
        import fitsio
    except ImportError:
        print('Skipping FITS tests, since fitsio is not installed')
        return

    # Check that running via the corr3 script works correctly.
    config = treecorr.config.read_config('configs/kkk_direct.yaml')
    cat.write(config['file_name'])
    treecorr.corr3(config)
    data = fitsio.read(config['kkk_file_name'])
    np.testing.assert_allclose(data['r_nom'], kkk.rnom.flatten())
    np.testing.assert_allclose(data['u_nom'], kkk.u.flatten())
    np.testing.assert_allclose(data['v_nom'], kkk.v.flatten())
    np.testing.assert_allclose(data['ntri'], kkk.ntri.flatten())
    np.testing.assert_allclose(data['weight'], kkk.weight.flatten())
    np.testing.assert_allclose(data['zeta'], kkk.zeta.flatten(), rtol=1.e-3)

    # Also check the "cross" calculation.  (Real cross doesn't work, but this should.)
    kkk = treecorr.KKKCorrelation(min_sep=min_sep,
                                  bin_size=bin_size,
                                  nbins=nrbins,
                                  brute=True)
    kkk.process(cat, cat, cat, num_threads=2)
    np.testing.assert_array_equal(kkk.ntri, true_ntri)
    np.testing.assert_allclose(kkk.weight, true_weight, rtol=1.e-5, atol=1.e-8)
    np.testing.assert_allclose(kkk.zeta, true_zeta, rtol=1.e-5, atol=1.e-8)

    config['file_name2'] = config['file_name']
    config['file_name3'] = config['file_name']
    treecorr.corr3(config)
    data = fitsio.read(config['kkk_file_name'])
    np.testing.assert_allclose(data['r_nom'], kkk.rnom.flatten())
    np.testing.assert_allclose(data['u_nom'], kkk.u.flatten())
    np.testing.assert_allclose(data['v_nom'], kkk.v.flatten())
    np.testing.assert_allclose(data['ntri'], kkk.ntri.flatten())
    np.testing.assert_allclose(data['weight'], kkk.weight.flatten())
    np.testing.assert_allclose(data['zeta'], kkk.zeta.flatten(), rtol=1.e-3)

    # Repeat with binslop = 0
    # And don't do any top-level recursion so we actually test not going to the leaves.
    kkk = treecorr.KKKCorrelation(min_sep=min_sep,
                                  bin_size=bin_size,
                                  nbins=nrbins,
                                  bin_slop=0,
                                  max_top=0)
    kkk.process(cat)
    np.testing.assert_array_equal(kkk.ntri, true_ntri)
    np.testing.assert_allclose(kkk.weight, true_weight, rtol=1.e-5, atol=1.e-8)
    np.testing.assert_allclose(kkk.zeta, true_zeta, rtol=1.e-5, atol=1.e-8)

    # Check a few basic operations with a GGCorrelation object.
    do_pickle(kkk)

    kkk2 = kkk.copy()
    kkk2 += kkk
    np.testing.assert_allclose(kkk2.ntri, 2 * kkk.ntri)
    np.testing.assert_allclose(kkk2.weight, 2 * kkk.weight)
    np.testing.assert_allclose(kkk2.meand1, 2 * kkk.meand1)
    np.testing.assert_allclose(kkk2.meand2, 2 * kkk.meand2)
    np.testing.assert_allclose(kkk2.meand3, 2 * kkk.meand3)
    np.testing.assert_allclose(kkk2.meanlogd1, 2 * kkk.meanlogd1)
    np.testing.assert_allclose(kkk2.meanlogd2, 2 * kkk.meanlogd2)
    np.testing.assert_allclose(kkk2.meanlogd3, 2 * kkk.meanlogd3)
    np.testing.assert_allclose(kkk2.meanu, 2 * kkk.meanu)
    np.testing.assert_allclose(kkk2.meanv, 2 * kkk.meanv)
    np.testing.assert_allclose(kkk2.zeta, 2 * kkk.zeta)

    kkk2.clear()
    kkk2 += kkk
    np.testing.assert_allclose(kkk2.ntri, kkk.ntri)
    np.testing.assert_allclose(kkk2.weight, kkk.weight)
    np.testing.assert_allclose(kkk2.meand1, kkk.meand1)
    np.testing.assert_allclose(kkk2.meand2, kkk.meand2)
    np.testing.assert_allclose(kkk2.meand3, kkk.meand3)
    np.testing.assert_allclose(kkk2.meanlogd1, kkk.meanlogd1)
    np.testing.assert_allclose(kkk2.meanlogd2, kkk.meanlogd2)
    np.testing.assert_allclose(kkk2.meanlogd3, kkk.meanlogd3)
    np.testing.assert_allclose(kkk2.meanu, kkk.meanu)
    np.testing.assert_allclose(kkk2.meanv, kkk.meanv)
    np.testing.assert_allclose(kkk2.zeta, kkk.zeta)

    ascii_name = 'output/kkk_ascii.txt'
    kkk.write(ascii_name, precision=16)
    kkk3 = treecorr.KKKCorrelation(min_sep=min_sep,
                                   bin_size=bin_size,
                                   nbins=nrbins)
    kkk3.read(ascii_name)
    np.testing.assert_allclose(kkk3.ntri, kkk.ntri)
    np.testing.assert_allclose(kkk3.weight, kkk.weight)
    np.testing.assert_allclose(kkk3.meand1, kkk.meand1)
    np.testing.assert_allclose(kkk3.meand2, kkk.meand2)
    np.testing.assert_allclose(kkk3.meand3, kkk.meand3)
    np.testing.assert_allclose(kkk3.meanlogd1, kkk.meanlogd1)
    np.testing.assert_allclose(kkk3.meanlogd2, kkk.meanlogd2)
    np.testing.assert_allclose(kkk3.meanlogd3, kkk.meanlogd3)
    np.testing.assert_allclose(kkk3.meanu, kkk.meanu)
    np.testing.assert_allclose(kkk3.meanv, kkk.meanv)
    np.testing.assert_allclose(kkk3.zeta, kkk.zeta)

    fits_name = 'output/kkk_fits.fits'
    kkk.write(fits_name)
    kkk4 = treecorr.KKKCorrelation(min_sep=min_sep,
                                   bin_size=bin_size,
                                   nbins=nrbins)
    kkk4.read(fits_name)
    np.testing.assert_allclose(kkk4.ntri, kkk.ntri)
    np.testing.assert_allclose(kkk4.weight, kkk.weight)
    np.testing.assert_allclose(kkk4.meand1, kkk.meand1)
    np.testing.assert_allclose(kkk4.meand2, kkk.meand2)
    np.testing.assert_allclose(kkk4.meand3, kkk.meand3)
    np.testing.assert_allclose(kkk4.meanlogd1, kkk.meanlogd1)
    np.testing.assert_allclose(kkk4.meanlogd2, kkk.meanlogd2)
    np.testing.assert_allclose(kkk4.meanlogd3, kkk.meanlogd3)
    np.testing.assert_allclose(kkk4.meanu, kkk.meanu)
    np.testing.assert_allclose(kkk4.meanv, kkk.meanv)
    np.testing.assert_allclose(kkk4.zeta, kkk.zeta)

    with assert_raises(TypeError):
        kkk2 += config
    kkk5 = treecorr.KKKCorrelation(min_sep=min_sep / 2,
                                   bin_size=bin_size,
                                   nbins=nrbins)
    with assert_raises(ValueError):
        kkk2 += kkk5
    kkk6 = treecorr.KKKCorrelation(min_sep=min_sep,
                                   bin_size=bin_size / 2,
                                   nbins=nrbins)
    with assert_raises(ValueError):
        kkk2 += kkk6
    kkk7 = treecorr.KKKCorrelation(min_sep=min_sep,
                                   bin_size=bin_size,
                                   nbins=nrbins * 2)
    with assert_raises(ValueError):
        kkk2 += kkk7
    kkk8 = treecorr.KKKCorrelation(min_sep=min_sep,
                                   bin_size=bin_size,
                                   nbins=nrbins,
                                   min_u=0.1)
    with assert_raises(ValueError):
        kkk2 += kkk8
    kkk0 = treecorr.KKKCorrelation(min_sep=min_sep,
                                   bin_size=bin_size,
                                   nbins=nrbins,
                                   max_u=0.1)
    with assert_raises(ValueError):
        kkk2 += kkk0
    kkk10 = treecorr.KKKCorrelation(min_sep=min_sep,
                                    bin_size=bin_size,
                                    nbins=nrbins,
                                    nubins=nrbins * 2)
    with assert_raises(ValueError):
        kkk2 += kkk10
    kkk11 = treecorr.KKKCorrelation(min_sep=min_sep,
                                    bin_size=bin_size,
                                    nbins=nrbins,
                                    min_v=0.1)
    with assert_raises(ValueError):
        kkk2 += kkk11
    kkk12 = treecorr.KKKCorrelation(min_sep=min_sep,
                                    bin_size=bin_size,
                                    nbins=nrbins,
                                    max_v=0.1)
    with assert_raises(ValueError):
        kkk2 += kkk12
    kkk13 = treecorr.KKKCorrelation(min_sep=min_sep,
                                    bin_size=bin_size,
                                    nbins=nrbins,
                                    nvbins=nrbins * 2)
    with assert_raises(ValueError):
        kkk2 += kkk13

    # Currently not implemented to only have cat2 or cat3
    with assert_raises(NotImplementedError):
        kkk.process(cat, cat2=cat)
    with assert_raises(NotImplementedError):
        kkk.process(cat, cat3=cat)
    with assert_raises(NotImplementedError):
        kkk.process_cross21(cat, cat)
Esempio n. 8
0
def corr3(config, logger=None):
    """Run the full three-point correlation function code based on the parameters in the
    given config dict.

    The function `print_corr3_params` will output information about the valid parameters
    that are expected to be in the config dict.

    Optionally a logger parameter maybe given, in which case it is used for logging.
    If not given, the logging will be based on the verbose and log_file parameters.

    :param config:  The configuration dict which defines what to do.
    :param 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.)
    """
    # Setup logger based on config verbose value
    if logger is None:
        logger = treecorr.config.setup_logger(
            treecorr.config.get(config, 'verbose', int, 1),
            config.get('log_file', None))

    # Check that config doesn't have any extra parameters.
    # (Such values are probably typos.)
    # Also convert the given parameters to the correct type, etc.
    config = treecorr.config.check_config(config, corr3_valid_params,
                                          corr3_aliases, logger)

    import pprint
    logger.debug('Using configuration dict:\n%s', pprint.pformat(config))

    if ('output_dots' not in config and config.get('log_file', None) is None
            and config['verbose'] >= 2):
        config['output_dots'] = True

    # Set the number of threads
    num_threads = config.get('num_threads', None)
    logger.debug('From config dict, num_threads = %s', num_threads)
    treecorr.set_omp_threads(num_threads, logger)

    # Read in the input files.  Each of these is a list.
    cat1 = treecorr.read_catalogs(config, 'file_name', 'file_list', 0, logger)
    cat2 = treecorr.read_catalogs(config, 'file_name2', 'rand_file_list2', 1,
                                  logger)
    cat3 = treecorr.read_catalogs(config, 'file_name3', 'rand_file_list3', 1,
                                  logger)
    rand1 = treecorr.read_catalogs(config, 'rand_file_name', 'rand_file_list',
                                   0, logger)
    rand2 = treecorr.read_catalogs(config, 'rand_file_name2',
                                   'rand_file_list2', 1, logger)
    rand3 = treecorr.read_catalogs(config, 'rand_file_name3',
                                   'rand_file_list3', 1, logger)
    if len(cat1) == 0:
        raise TypeError("Either file_name or file_list is required")
    if len(cat2) == 0: cat2 = None
    if len(cat3) == 0: cat3 = None
    if len(rand1) == 0: rand1 = None
    if len(rand2) == 0: rand2 = None
    if len(rand3) == 0: rand3 = None
    if cat2 is None and rand2 is not None:
        raise TypeError("rand_file_name2 is invalid without file_name2")
    if cat3 is None and rand3 is not None:
        raise TypeError("rand_file_name3 is invalid without file_name3")
    if (cat2 is None) != (cat3 is None):
        raise NotImplementedError(
            "Cannot yet handle 3-point corrleations with only two catalogs. " +
            "Need both cat2 and cat3.")
    logger.info("Done reading input catalogs")

    # Do GGG correlation function if necessary
    if 'ggg_file_name' in config or 'm3_file_name' in config:
        logger.warning("Performing GGG calculations...")
        ggg = treecorr.GGGCorrelation(config, logger)
        ggg.process(cat1, cat2, cat3)
        logger.info("Done GGG calculations.")
        if 'ggg_file_name' in config:
            ggg.write(config['ggg_file_name'])
            logger.warning("Wrote GGG correlation to %s",
                           config['ggg_file_name'])
        if 'm3_file_name' in config:
            ggg.writeMap3(config['m3_file_name'])
            logger.warning("Wrote Map3 values to %s", config['m3_file_name'])

    # Do NNN correlation function if necessary
    if 'nnn_file_name' in config:
        logger.warning("Performing DDD calculations...")
        ddd = treecorr.NNNCorrelation(config, logger)
        ddd.process(cat1, cat2, cat3)
        logger.info("Done DDD calculations.")

        drr = None
        rdr = None
        rrd = None
        ddr = None
        drd = None
        rdd = None
        if rand1 is None:
            if rand2 is not None or rand3 is not None:
                raise TypeError(
                    "rand_file_name is required if rand2 or rand3 is given")
            logger.warning(
                "No random catalogs given.  Only doing ntri calculation.")
            rrr = None
        elif cat2 is None:
            logger.warning("Performing RRR calculations...")
            rrr = treecorr.NNNCorrelation(config, logger)
            rrr.process(rand1)
            logger.info("Done RRR calculations.")

            # For the next step, just make cat2 = cat3 = cat1 and rand2 = rand3 = rand1.
            cat2 = cat3 = cat1
            rand2 = rand3 = rand1
        else:
            if rand2 is None:
                raise TypeError(
                    "rand_file_name2 is required when file_name2 is given")
            if cat3 is not None and rand3 is None:
                raise TypeError(
                    "rand_file_name3 is required when file_name3 is given")
            logger.warning("Performing RRR calculations...")
            rrr = treecorr.NNNCorrelation(config, logger)
            rrr.process(rand1, rand2, rand3)
            logger.info("Done RRR calculations.")

        if rrr is not None and config['nnn_statistic'] == 'compensated':
            logger.warning("Performing DRR calculations...")
            drr = treecorr.NNNCorrelation(config, logger)
            drr.process(cat1, rand2, rand3)
            logger.info("Done DRR calculations.")
            logger.warning("Performing DDR calculations...")
            ddr = treecorr.NNNCorrelation(config, logger)
            ddr.process(cat1, cat2, rand3)
            logger.info("Done DDR calculations.")
            logger.warning("Performing RDR calculations...")
            rdr = treecorr.NNNCorrelation(config, logger)
            rdr.process(rand1, cat2, rand3)
            logger.info("Done RDR calculations.")
            logger.warning("Performing RRD calculations...")
            rrd = treecorr.NNNCorrelation(config, logger)
            rrd.process(rand1, rand2, cat3)
            logger.info("Done RRD calculations.")
            logger.warning("Performing DRD calculations...")
            drd = treecorr.NNNCorrelation(config, logger)
            drd.process(cat1, rand2, cat3)
            logger.info("Done DRD calculations.")
            logger.warning("Performing RDD calculations...")
            rdd = treecorr.NNNCorrelation(config, logger)
            rdd.process(rand1, cat2, cat3)
            logger.info("Done RDD calculations.")
        ddd.write(config['nnn_file_name'], rrr, drr, rdr, rrd, ddr, drd, rdd)
        logger.warning("Wrote NNN correlation to %s", config['nnn_file_name'])

    # Do KKK correlation function if necessary
    if 'kkk_file_name' in config:
        logger.warning("Performing KKK calculations...")
        kkk = treecorr.KKKCorrelation(config, logger)
        kkk.process(cat1, cat2, cat3)
        logger.info("Done KKK calculations.")
        kkk.write(config['kkk_file_name'])
        logger.warning("Wrote KKK correlation to %s", config['kkk_file_name'])
Esempio n. 9
0
def test_kkk():
    # Use kappa(r) = A exp(-r^2/2s^2)
    #
    # The Fourier transform is: kappa~(k) = 2 pi A s^2 exp(-s^2 k^2/2) / L^2
    #
    # B(k1,k2) = <k~(k1) k~(k2) k~(-k1-k2)>
    #          = (2 pi A (s/L)^2)^3 exp(-s^2 (|k1|^2 + |k2|^2 - k1.k2))
    #          = (2 pi A (s/L)^2)^3 exp(-s^2 (|k1|^2 + |k2|^2 + |k3|^2)/2)
    #
    # zeta(r1,r2) = (1/2pi)^4 int(d^2k1 int(d^2k2 exp(ik1.x1) exp(ik2.x2) B(k1,k2) ))
    #             = 2/3 pi A^3 (s/L)^2 exp(-(x1^2 + y1^2 + x2^2 + y2^2 - x1x2 - y1y2)/3s^2)
    #             = 2/3 pi A^3 (s/L)^2 exp(-(d1^2 + d2^2 + d3^2)/6s^2)

    A = 0.05
    s = 10.
    if __name__ == '__main__':
        ngal = 200000
        L = 30. * s  # Not infinity, so this introduces some error.  Our integrals were to infinity.
        req_factor = 1
    else:
        # Looser tests from nosetests that don't take so long to run.
        ngal = 5000
        L = 10. * s
        req_factor = 5
    numpy.random.seed(8675309)
    x = (numpy.random.random_sample(ngal) - 0.5) * L
    y = (numpy.random.random_sample(ngal) - 0.5) * L
    r2 = (x**2 + y**2) / s**2
    kappa = A * numpy.exp(-r2 / 2.)

    min_sep = 11.
    max_sep = 15.
    nbins = 3
    min_u = 0.7
    max_u = 1.0
    nubins = 3
    min_v = -0.1
    max_v = 0.3
    nvbins = 4

    cat = treecorr.Catalog(x=x,
                           y=y,
                           k=kappa,
                           x_units='arcmin',
                           y_units='arcmin')
    kkk = treecorr.KKKCorrelation(min_sep=min_sep,
                                  max_sep=max_sep,
                                  nbins=nbins,
                                  min_u=min_u,
                                  max_u=max_u,
                                  min_v=min_v,
                                  max_v=max_v,
                                  nubins=nubins,
                                  nvbins=nvbins,
                                  sep_units='arcmin',
                                  verbose=1)
    kkk.process(cat)

    # log(<d>) != <logd>, but it should be close:
    #print('meanlogd1 - log(meand1) = ',kkk.meanlogd1 - numpy.log(kkk.meand1))
    #print('meanlogd2 - log(meand2) = ',kkk.meanlogd2 - numpy.log(kkk.meand2))
    #print('meanlogd3 - log(meand3) = ',kkk.meanlogd3 - numpy.log(kkk.meand3))
    #print('meanlogd3 - meanlogd2 - log(meanu) = ',kkk.meanlogd3 - kkk.meanlogd2 - numpy.log(kkk.meanu))
    #print('log(meand1-meand2) - meanlogd3 - log(meanv) = ',numpy.log(kkk.meand1-kkk.meand2) - kkk.meanlogd3 - numpy.log(numpy.abs(kkk.meanv)))
    numpy.testing.assert_almost_equal(kkk.meanlogd1,
                                      numpy.log(kkk.meand1),
                                      decimal=3)
    numpy.testing.assert_almost_equal(kkk.meanlogd2,
                                      numpy.log(kkk.meand2),
                                      decimal=3)
    numpy.testing.assert_almost_equal(kkk.meanlogd3,
                                      numpy.log(kkk.meand3),
                                      decimal=3)
    numpy.testing.assert_almost_equal(kkk.meanlogd3 - kkk.meanlogd2,
                                      numpy.log(kkk.meanu),
                                      decimal=3)
    numpy.testing.assert_almost_equal(numpy.log(kkk.meand1 - kkk.meand2) -
                                      kkk.meanlogd3,
                                      numpy.log(numpy.abs(kkk.meanv)),
                                      decimal=3)

    d1 = kkk.meand1
    d2 = kkk.meand2
    d3 = kkk.meand3
    #print('rnom = ',numpy.exp(kkk.logr))
    #print('unom = ',kkk.u)
    #print('vnom = ',kkk.v)
    #print('d1 = ',d1)
    #print('d2 = ',d2)
    #print('d3 = ',d3)
    # The L^2 term in the denominator of true_zeta is the area over which the integral is done.
    # Since the centers of the triangles don't go to the edge of the box, we approximate the
    # correct area by subtracting off 2d2 from L, which should give a slightly better estimate
    # of the correct area to use here.
    L = L - 2. * d2
    true_zeta = (2. * numpy.pi / 3) * A**3 * (s / L)**2 * numpy.exp(
        -(d1**2 + d2**2 + d3**2) / (6. * s**2))

    #print('ntri = ',kkk.ntri)
    print('zeta = ', kkk.zeta)
    print('true_zeta = ', true_zeta)
    #print('ratio = ',kkk.zeta / true_zeta)
    #print('diff = ',kkk.zeta - true_zeta)
    print('max rel diff = ',
          numpy.max(numpy.abs((kkk.zeta - true_zeta) / true_zeta)))
    assert numpy.max(numpy.abs(
        (kkk.zeta - true_zeta) / true_zeta)) / req_factor < 0.1
    numpy.testing.assert_almost_equal(
        numpy.log(numpy.abs(kkk.zeta)) / req_factor,
        numpy.log(numpy.abs(true_zeta)) / req_factor,
        decimal=1)

    # Check that we get the same result using the corr3 executable:
    if __name__ == '__main__':
        cat.write(os.path.join('data', 'kkk_data.dat'))
        import subprocess
        corr3_exe = get_script_name('corr3')
        p = subprocess.Popen([corr3_exe, "kkk.yaml"])
        p.communicate()
        corr3_output = numpy.genfromtxt(os.path.join('output', 'kkk.out'),
                                        names=True)
        #print('zeta = ',kkk.zeta)
        #print('from corr3 output = ',corr3_output['zeta'])
        #print('ratio = ',corr3_output['zeta']/kkk.zeta.flatten())
        #print('diff = ',corr3_output['zeta']-kkk.zeta.flatten())
        numpy.testing.assert_almost_equal(corr3_output['zeta'] /
                                          kkk.zeta.flatten(),
                                          1.,
                                          decimal=3)

    # Check the fits write option
    out_file_name = os.path.join('output', 'kkk_out.fits')
    kkk.write(out_file_name)
    data = fitsio.read(out_file_name)
    numpy.testing.assert_almost_equal(data['R_nom'],
                                      numpy.exp(kkk.logr).flatten())
    numpy.testing.assert_almost_equal(data['u_nom'], kkk.u.flatten())
    numpy.testing.assert_almost_equal(data['v_nom'], kkk.v.flatten())
    numpy.testing.assert_almost_equal(data['meand1'], kkk.meand1.flatten())
    numpy.testing.assert_almost_equal(data['meanlogd1'],
                                      kkk.meanlogd1.flatten())
    numpy.testing.assert_almost_equal(data['meand2'], kkk.meand2.flatten())
    numpy.testing.assert_almost_equal(data['meanlogd2'],
                                      kkk.meanlogd2.flatten())
    numpy.testing.assert_almost_equal(data['meand3'], kkk.meand3.flatten())
    numpy.testing.assert_almost_equal(data['meanlogd3'],
                                      kkk.meanlogd3.flatten())
    numpy.testing.assert_almost_equal(data['meanu'], kkk.meanu.flatten())
    numpy.testing.assert_almost_equal(data['meanv'], kkk.meanv.flatten())
    numpy.testing.assert_almost_equal(data['zeta'], kkk.zeta.flatten())
    numpy.testing.assert_almost_equal(data['sigma_zeta'],
                                      numpy.sqrt(kkk.varzeta.flatten()))
    numpy.testing.assert_almost_equal(data['weight'], kkk.weight.flatten())
    numpy.testing.assert_almost_equal(data['ntri'], kkk.ntri.flatten())

    # Check the read function
    # Note: These don't need the flatten. The read function should reshape them to the right shape.
    kkk2 = treecorr.KKKCorrelation(min_sep=min_sep,
                                   max_sep=max_sep,
                                   nbins=nbins,
                                   min_u=min_u,
                                   max_u=max_u,
                                   min_v=min_v,
                                   max_v=max_v,
                                   nubins=nubins,
                                   nvbins=nvbins,
                                   sep_units='arcmin',
                                   verbose=1)
    kkk2.read(out_file_name)
    numpy.testing.assert_almost_equal(kkk2.logr, kkk.logr)
    numpy.testing.assert_almost_equal(kkk2.u, kkk.u)
    numpy.testing.assert_almost_equal(kkk2.v, kkk.v)
    numpy.testing.assert_almost_equal(kkk2.meand1, kkk.meand1)
    numpy.testing.assert_almost_equal(kkk2.meanlogd1, kkk.meanlogd1)
    numpy.testing.assert_almost_equal(kkk2.meand2, kkk.meand2)
    numpy.testing.assert_almost_equal(kkk2.meanlogd2, kkk.meanlogd2)
    numpy.testing.assert_almost_equal(kkk2.meand3, kkk.meand3)
    numpy.testing.assert_almost_equal(kkk2.meanlogd3, kkk.meanlogd3)
    numpy.testing.assert_almost_equal(kkk2.meanu, kkk.meanu)
    numpy.testing.assert_almost_equal(kkk2.meanv, kkk.meanv)
    numpy.testing.assert_almost_equal(kkk2.zeta, kkk.zeta)
    numpy.testing.assert_almost_equal(kkk2.varzeta, kkk.varzeta)
    numpy.testing.assert_almost_equal(kkk2.weight, kkk.weight)
    numpy.testing.assert_almost_equal(kkk2.ntri, kkk.ntri)