pyerrors.jackknifing

View Source
#!/usr/bin/env python
# coding: utf-8

import pickle
import matplotlib.pyplot as plt
import numpy as np


def _jack_error(jack):
    n = jack.size
    mean = np.mean(jack)
    error = 0
    for i in range(n):
        error += (jack[i] - mean) ** 2

    return np.sqrt((n - 1) / n * error)


class Jack:

    def __init__(self, value, jacks):
        self.jacks = jacks
        self.N = list(map(np.size, self.jacks))
        self.max_binsize = len(self.N)
        self.value = value  # list(map(np.mean, self.jacks))
        self.dvalue = list(map(_jack_error, self.jacks))

    def print(self, **kwargs):
        """Print basic properties of the Jack."""

        if 'binsize' in kwargs:
            b = kwargs.get('binsize') - 1
            if b == -1:
                b = 0
            if not isinstance(b, int):
                raise TypeError('binsize has to be integer')
            if b + 1 > self.max_binsize:
                raise Exception('Chosen binsize not calculated')
        else:
            b = 0

        print('Result:\t %3.8e +/- %3.8e +/- %3.8e (%3.3f%%)' % (self.value, self.dvalue[b], self.dvalue[b] * np.sqrt(2 * b / self.N[0]), np.abs(self.dvalue[b] / self.value * 100)))

    def plot_tauint(self):
        plt.xlabel('binsize')
        plt.ylabel('tauint')
        length = self.max_binsize
        x = np.arange(length) + 1
        plt.errorbar(x[:], (self.dvalue[:] / self.dvalue[0]) ** 2 / 2, yerr=np.sqrt(((2 * (self.dvalue[:] / self.dvalue[0]) ** 2 * np.sqrt(2 * x[:] / self.N[0])) / 2) ** 2 + ((2 * (self.dvalue[:] / self.dvalue[0]) ** 2 * np.sqrt(2 / self.N[0])) / 2) ** 2), linewidth=1, capsize=2)
        plt.xlim(0.5, length + 0.5)
        plt.title('Tauint')
        plt.show()

    def plot_history(self):
        N = self.N
        x = np.arange(N)
        tmp = []
        for i in range(self.replicas):
            tmp.append(self.deltas[i] + self.r_values[i])
        y = np.concatenate(tmp, axis=0)  # Think about including kwarg to look only at some replica
        plt.errorbar(x, y, fmt='.', markersize=3)
        plt.xlim(-0.5, N - 0.5)
        plt.show()

    def dump(self, name, **kwargs):
        """Dump the Jack to a pickle file 'name'.

        Keyword arguments:
        path -- specifies a custom path for the file (default '.')
        """
        if 'path' in kwargs:
            file_name = kwargs.get('path') + '/' + name + '.p'
        else:
            file_name = name + '.p'
        with open(file_name, 'wb') as fb:
            pickle.dump(self, fb)


def generate_jack(obs, **kwargs):
    full_data = []
    for r, name in enumerate(obs.names):
        if r == 0:
            full_data = obs.deltas[name] + obs.r_values[name]
        else:
            full_data = np.append(full_data, obs.deltas[name] + obs.r_values[name])

    jacks = []
    if 'max_binsize' in kwargs:
        max_b = kwargs.get('max_binsize')
        if not isinstance(max_b, int):
            raise TypeError('max_binsize has to be integer')
    else:
        max_b = 1

    for b in range(max_b):
        # binning if necessary
        if b > 0:
            n = full_data.size // (b + 1)
            binned_data = np.zeros(n)
            for i in range(n):
                for j in range(b + 1):
                    binned_data[i] += full_data[i * (b + 1) + j]
                binned_data[i] /= (b + 1)
        else:
            binned_data = full_data
            n = binned_data.size
        # generate jacks from data
        mean = np.mean(binned_data)
        tmp_jacks = np.zeros(n)
        for i in range(n):
            tmp_jacks[i] = (n * mean - binned_data[i]) / (n - 1)
        jacks.append(tmp_jacks)

        # Value is not correctly reproduced here
    return Jack(obs.value, jacks)


def derived_jack(func, data, **kwargs):
    """Construct a derived Jack according to func(data, **kwargs).

    Parameters
    ----------
    func -- arbitrary function of the form func(data, **kwargs). For the automatic differentiation to work,
            all numpy functions have to have the autograd wrapper (use 'import autograd.numpy as np').
    data -- list of Jacks, e.g. [jack1, jack2, jack3].

    Notes
    -----
    For simple mathematical operations it can be practical to use anonymous functions.
    For the ratio of two jacks one can e.g. use

    new_jack = derived_jack(lambda x : x[0] / x[1], [jack1, jack2])

    """

    # Check shapes of data
    if not all(x.N == data[0].N for x in data):
        raise Exception('Error: Shape of data does not fit')

    values = np.zeros(len(data))
    for j, item in enumerate(data):
        values[j] = item.value
    new_value = func(values, **kwargs)

    jacks = []
    for b in range(data[0].max_binsize):
        tmp_jacks = np.zeros(data[0].N[b])
        for i in range(data[0].N[b]):
            values = np.zeros(len(data))
            for j, item in enumerate(data):
                values[j] = item.jacks[b][i]
            tmp_jacks[i] = func(values, **kwargs)
        jacks.append(tmp_jacks)

    return Jack(new_value, jacks)
#   class Jack:
View Source
class Jack:

    def __init__(self, value, jacks):
        self.jacks = jacks
        self.N = list(map(np.size, self.jacks))
        self.max_binsize = len(self.N)
        self.value = value  # list(map(np.mean, self.jacks))
        self.dvalue = list(map(_jack_error, self.jacks))

    def print(self, **kwargs):
        """Print basic properties of the Jack."""

        if 'binsize' in kwargs:
            b = kwargs.get('binsize') - 1
            if b == -1:
                b = 0
            if not isinstance(b, int):
                raise TypeError('binsize has to be integer')
            if b + 1 > self.max_binsize:
                raise Exception('Chosen binsize not calculated')
        else:
            b = 0

        print('Result:\t %3.8e +/- %3.8e +/- %3.8e (%3.3f%%)' % (self.value, self.dvalue[b], self.dvalue[b] * np.sqrt(2 * b / self.N[0]), np.abs(self.dvalue[b] / self.value * 100)))

    def plot_tauint(self):
        plt.xlabel('binsize')
        plt.ylabel('tauint')
        length = self.max_binsize
        x = np.arange(length) + 1
        plt.errorbar(x[:], (self.dvalue[:] / self.dvalue[0]) ** 2 / 2, yerr=np.sqrt(((2 * (self.dvalue[:] / self.dvalue[0]) ** 2 * np.sqrt(2 * x[:] / self.N[0])) / 2) ** 2 + ((2 * (self.dvalue[:] / self.dvalue[0]) ** 2 * np.sqrt(2 / self.N[0])) / 2) ** 2), linewidth=1, capsize=2)
        plt.xlim(0.5, length + 0.5)
        plt.title('Tauint')
        plt.show()

    def plot_history(self):
        N = self.N
        x = np.arange(N)
        tmp = []
        for i in range(self.replicas):
            tmp.append(self.deltas[i] + self.r_values[i])
        y = np.concatenate(tmp, axis=0)  # Think about including kwarg to look only at some replica
        plt.errorbar(x, y, fmt='.', markersize=3)
        plt.xlim(-0.5, N - 0.5)
        plt.show()

    def dump(self, name, **kwargs):
        """Dump the Jack to a pickle file 'name'.

        Keyword arguments:
        path -- specifies a custom path for the file (default '.')
        """
        if 'path' in kwargs:
            file_name = kwargs.get('path') + '/' + name + '.p'
        else:
            file_name = name + '.p'
        with open(file_name, 'wb') as fb:
            pickle.dump(self, fb)
#   Jack(value, jacks)
View Source
    def __init__(self, value, jacks):
        self.jacks = jacks
        self.N = list(map(np.size, self.jacks))
        self.max_binsize = len(self.N)
        self.value = value  # list(map(np.mean, self.jacks))
        self.dvalue = list(map(_jack_error, self.jacks))
#   def print(self, **kwargs):
View Source
    def print(self, **kwargs):
        """Print basic properties of the Jack."""

        if 'binsize' in kwargs:
            b = kwargs.get('binsize') - 1
            if b == -1:
                b = 0
            if not isinstance(b, int):
                raise TypeError('binsize has to be integer')
            if b + 1 > self.max_binsize:
                raise Exception('Chosen binsize not calculated')
        else:
            b = 0

        print('Result:\t %3.8e +/- %3.8e +/- %3.8e (%3.3f%%)' % (self.value, self.dvalue[b], self.dvalue[b] * np.sqrt(2 * b / self.N[0]), np.abs(self.dvalue[b] / self.value * 100)))

Print basic properties of the Jack.

#   def plot_tauint(self):
View Source
    def plot_tauint(self):
        plt.xlabel('binsize')
        plt.ylabel('tauint')
        length = self.max_binsize
        x = np.arange(length) + 1
        plt.errorbar(x[:], (self.dvalue[:] / self.dvalue[0]) ** 2 / 2, yerr=np.sqrt(((2 * (self.dvalue[:] / self.dvalue[0]) ** 2 * np.sqrt(2 * x[:] / self.N[0])) / 2) ** 2 + ((2 * (self.dvalue[:] / self.dvalue[0]) ** 2 * np.sqrt(2 / self.N[0])) / 2) ** 2), linewidth=1, capsize=2)
        plt.xlim(0.5, length + 0.5)
        plt.title('Tauint')
        plt.show()
#   def plot_history(self):
View Source
    def plot_history(self):
        N = self.N
        x = np.arange(N)
        tmp = []
        for i in range(self.replicas):
            tmp.append(self.deltas[i] + self.r_values[i])
        y = np.concatenate(tmp, axis=0)  # Think about including kwarg to look only at some replica
        plt.errorbar(x, y, fmt='.', markersize=3)
        plt.xlim(-0.5, N - 0.5)
        plt.show()
#   def dump(self, name, **kwargs):
View Source
    def dump(self, name, **kwargs):
        """Dump the Jack to a pickle file 'name'.

        Keyword arguments:
        path -- specifies a custom path for the file (default '.')
        """
        if 'path' in kwargs:
            file_name = kwargs.get('path') + '/' + name + '.p'
        else:
            file_name = name + '.p'
        with open(file_name, 'wb') as fb:
            pickle.dump(self, fb)

Dump the Jack to a pickle file 'name'.

Keyword arguments: path -- specifies a custom path for the file (default '.')

#   def generate_jack(obs, **kwargs):
View Source
def generate_jack(obs, **kwargs):
    full_data = []
    for r, name in enumerate(obs.names):
        if r == 0:
            full_data = obs.deltas[name] + obs.r_values[name]
        else:
            full_data = np.append(full_data, obs.deltas[name] + obs.r_values[name])

    jacks = []
    if 'max_binsize' in kwargs:
        max_b = kwargs.get('max_binsize')
        if not isinstance(max_b, int):
            raise TypeError('max_binsize has to be integer')
    else:
        max_b = 1

    for b in range(max_b):
        # binning if necessary
        if b > 0:
            n = full_data.size // (b + 1)
            binned_data = np.zeros(n)
            for i in range(n):
                for j in range(b + 1):
                    binned_data[i] += full_data[i * (b + 1) + j]
                binned_data[i] /= (b + 1)
        else:
            binned_data = full_data
            n = binned_data.size
        # generate jacks from data
        mean = np.mean(binned_data)
        tmp_jacks = np.zeros(n)
        for i in range(n):
            tmp_jacks[i] = (n * mean - binned_data[i]) / (n - 1)
        jacks.append(tmp_jacks)

        # Value is not correctly reproduced here
    return Jack(obs.value, jacks)
#   def derived_jack(func, data, **kwargs):
View Source
def derived_jack(func, data, **kwargs):
    """Construct a derived Jack according to func(data, **kwargs).

    Parameters
    ----------
    func -- arbitrary function of the form func(data, **kwargs). For the automatic differentiation to work,
            all numpy functions have to have the autograd wrapper (use 'import autograd.numpy as np').
    data -- list of Jacks, e.g. [jack1, jack2, jack3].

    Notes
    -----
    For simple mathematical operations it can be practical to use anonymous functions.
    For the ratio of two jacks one can e.g. use

    new_jack = derived_jack(lambda x : x[0] / x[1], [jack1, jack2])

    """

    # Check shapes of data
    if not all(x.N == data[0].N for x in data):
        raise Exception('Error: Shape of data does not fit')

    values = np.zeros(len(data))
    for j, item in enumerate(data):
        values[j] = item.value
    new_value = func(values, **kwargs)

    jacks = []
    for b in range(data[0].max_binsize):
        tmp_jacks = np.zeros(data[0].N[b])
        for i in range(data[0].N[b]):
            values = np.zeros(len(data))
            for j, item in enumerate(data):
                values[j] = item.jacks[b][i]
            tmp_jacks[i] = func(values, **kwargs)
        jacks.append(tmp_jacks)

    return Jack(new_value, jacks)

Construct a derived Jack according to func(data, **kwargs).

Parameters
  • func -- arbitrary function of the form func(data, **kwargs). For the automatic differentiation to work,: all numpy functions have to have the autograd wrapper (use 'import autograd.numpy as np').
  • data -- list of Jacks, e.g. [jack1, jack2, jack3].
Notes

For simple mathematical operations it can be practical to use anonymous functions. For the ratio of two jacks one can e.g. use

new_jack = derived_jack(lambda x : x[0] / x[1], [jack1, jack2])