# Path: pwkit/numutil.py
# def weighted_variance(x, weights):
#     """Return the variance of a weighted sample.
# 
#     The weighted sample mean is calculated and subtracted off, so the returned
#     variance is upweighted by ``n / (n - 1)``. If the sample mean is known to
#     be zero, you should just compute ``np.average(x**2, weights=weights)``.
# 
#     """
#     n = len(x)
#     if n < 3:
#         raise ValueError('cannot calculate meaningful variance of fewer '
#                          'than three samples')
#     wt_mean = np.average(x, weights=weights)
#     return np.average(np.square(x - wt_mean), weights=weights) * n / (n - 1)
# 
# Path: pwkit/parallel.py
# def make_parallel_helper(parallel_arg, **kwargs):
#     """Return a :class:`ParallelHelper` object that can be used for easy
#     parallelization of computations. *parallel_arg* is an object that lets the
#     caller easily specify the kind of parallelization they are interested in.
#     Allowed values are:
# 
#     False
#       Serial processing only.
#     True
#       Parallel processing using all available cores.
#     1
#       Equivalent to ``False``.
#     Other positive integer
#       Parallel processing using the specified number of cores.
#     x, 0 < x < 1
#       Parallel processing using about ``x * N`` cores, where N is the total
#       number of cores in the system. Note that the meanings of ``0.99`` and ``1``
#       as arguments are very different.
#     :class:`ParallelHelper` instance
#       Returns the instance.
# 
#     The ``**kwargs`` are passed on to the appropriate :class:`ParallelHelper`
#     constructor, if the caller wants to do something tricky.
# 
#     Expected usage is::
# 
#         from pwkit.parallel import make_parallel_helper
# 
#         def sub_operation(arg):
#             ... do some computation ...
#             return result
# 
#         def my_parallelizable_function(arg1, arg2, parallel=True):
#             phelp = make_parallel_helper(parallel)
# 
#             with phelp.get_map() as map:
#                 op_results = map(sub_operation, args)
# 
#             ... reduce "op_results" in some way ...
#             return final_result
# 
#     This means that ``my_parallelizable_function`` doesn't have to worry about
#     all of the various fancy things the caller might want to do in terms of
#     special parallel magic.
# 
#     Note that ``sub_operation`` above must be defined in a stand-alone fashion
#     because of the way Python's :mod:`multiprocessing` module works. This can
#     be worked around somewhat with the special
#     :meth:`ParallelHelper.get_ppmap` variant. This returns a
#     "partially-Pickling" map operation --- with a different calling signature
#     --- that allows un-Pickle-able values to be used. See the documentation
#     for :func:`serial_ppmap` for usage information.
# 
#     """
#     if parallel_arg is True: # note: (True == 1) is True
#         return MultiprocessingPoolHelper(**kwargs)
# 
#     if parallel_arg is False or parallel_arg == 1:
#         return SerialHelper(**kwargs)
# 
#     if parallel_arg > 0 and parallel_arg < 1:
#         from multiprocessing import cpu_count
#         n = int(round(parallel_arg * cpu_count()))
#         return MultiprocessingPoolHelper(processes=n, **kwargs)
# 
#     if isinstance(parallel_arg, ParallelHelper):
#         return parallel_arg
# 
#     if isinstance(parallel_arg, six.integer_types):
#         return MultiprocessingPoolHelper(processes=parallel_arg, **kwargs)
# 
#     raise ValueError('don\'t understand make_parallel_helper() argument %r'
#                      % parallel_arg)


import numpy as np
from collections import namedtuple
from six.moves import range
from .numutil import weighted_variance
from .parallel import make_parallel_helper

    if x.shape != t.shape:
        raise ValueError ('`t` and `x` arguments must be the same size')

    if u.shape != t.shape:
        raise ValueError ('`t` and `u` arguments must be the same size')

    if periods.ndim != 1:
        raise ValueError ('`periods` must be <= 1D')

    if nbin < 2:
        raise ValueError ('`nbin` must be at least 2')

    if nshift < 1:
        raise ValueError ('`nshift` must be at least 1')

    if nsmc < 0:
        raise ValueError ('`nsmc` must be nonnegative')

    if numc < 0:
        raise ValueError ('`numc` must be nonnegative')

    # We can finally get started!

    if weights:
        wt = u
        u = wt ** -0.5
    else:
        wt = u ** -2


# Path: pwkit/numutil.py
# def weighted_variance(x, weights):
#     """Return the variance of a weighted sample.
# 
#     The weighted sample mean is calculated and subtracted off, so the returned
#     variance is upweighted by ``n / (n - 1)``. If the sample mean is known to
#     be zero, you should just compute ``np.average(x**2, weights=weights)``.
# 
#     """
#     n = len(x)
#     if n < 3:
#         raise ValueError('cannot calculate meaningful variance of fewer '
#                          'than three samples')
#     wt_mean = np.average(x, weights=weights)
#     return np.average(np.square(x - wt_mean), weights=weights) * n / (n - 1)
# 
# Path: pwkit/parallel.py
# def make_parallel_helper(parallel_arg, **kwargs):
#     """Return a :class:`ParallelHelper` object that can be used for easy
#     parallelization of computations. *parallel_arg* is an object that lets the
#     caller easily specify the kind of parallelization they are interested in.
#     Allowed values are:
# 
#     False
#       Serial processing only.
#     True
#       Parallel processing using all available cores.
#     1
#       Equivalent to ``False``.
#     Other positive integer
#       Parallel processing using the specified number of cores.
#     x, 0 < x < 1
#       Parallel processing using about ``x * N`` cores, where N is the total
#       number of cores in the system. Note that the meanings of ``0.99`` and ``1``
#       as arguments are very different.
#     :class:`ParallelHelper` instance
#       Returns the instance.
# 
#     The ``**kwargs`` are passed on to the appropriate :class:`ParallelHelper`
#     constructor, if the caller wants to do something tricky.
# 
#     Expected usage is::
# 
#         from pwkit.parallel import make_parallel_helper
# 
#         def sub_operation(arg):
#             ... do some computation ...
#             return result
# 
#         def my_parallelizable_function(arg1, arg2, parallel=True):
#             phelp = make_parallel_helper(parallel)
# 
#             with phelp.get_map() as map:
#                 op_results = map(sub_operation, args)
# 
#             ... reduce "op_results" in some way ...
#             return final_result
# 
#     This means that ``my_parallelizable_function`` doesn't have to worry about
#     all of the various fancy things the caller might want to do in terms of
#     special parallel magic.
# 
#     Note that ``sub_operation`` above must be defined in a stand-alone fashion
#     because of the way Python's :mod:`multiprocessing` module works. This can
#     be worked around somewhat with the special
#     :meth:`ParallelHelper.get_ppmap` variant. This returns a
#     "partially-Pickling" map operation --- with a different calling signature
#     --- that allows un-Pickle-able values to be used. See the documentation
#     for :func:`serial_ppmap` for usage information.
# 
#     """
#     if parallel_arg is True: # note: (True == 1) is True
#         return MultiprocessingPoolHelper(**kwargs)
# 
#     if parallel_arg is False or parallel_arg == 1:
#         return SerialHelper(**kwargs)
# 
#     if parallel_arg > 0 and parallel_arg < 1:
#         from multiprocessing import cpu_count
#         n = int(round(parallel_arg * cpu_count()))
#         return MultiprocessingPoolHelper(processes=n, **kwargs)
# 
#     if isinstance(parallel_arg, ParallelHelper):
#         return parallel_arg
# 
#     if isinstance(parallel_arg, six.integer_types):
#         return MultiprocessingPoolHelper(processes=parallel_arg, **kwargs)
# 
#     raise ValueError('don\'t understand make_parallel_helper() argument %r'
#                      % parallel_arg)


# Path: pwkit/pdm.py
import numpy as np
from collections import namedtuple
from six.moves import range
from .numutil import weighted_variance
from .parallel import make_parallel_helper


    if x.shape != t.shape:
        raise ValueError ('`t` and `x` arguments must be the same size')

    if u.shape != t.shape:
        raise ValueError ('`t` and `u` arguments must be the same size')

    if periods.ndim != 1:
        raise ValueError ('`periods` must be <= 1D')

    if nbin < 2:
        raise ValueError ('`nbin` must be at least 2')

    if nshift < 1:
        raise ValueError ('`nshift` must be at least 1')

    if nsmc < 0:
        raise ValueError ('`nsmc` must be nonnegative')

    if numc < 0:
        raise ValueError ('`numc` must be nonnegative')

    # We can finally get started!

    if weights:
        wt = u
        u = wt ** -0.5
    else:
        wt = u ** -2


    v_all = weighted_variance (x, wt)