# Path: pytim/observables/basic_observables.py
# class Number(Observable):
#     """The number of atoms.
#     """
# 
#     def __init__(self, *arg, **kwarg):
#         Observable.__init__(self, None)
# 
#     def compute(self, inp, kargs=None):
#         """Compute the observable.
# 
#         :param AtomGroup inp:  the input atom group
#         :returns: one, for each atom in the group
# 
#         """
#         return np.ones(len(inp))
# 
# Path: pytim/observables/intrinsic_distance.py
# class IntrinsicDistance(Observable):
#     """Initialize the intrinsic distance calculation.
# 
#     :param PYTIM interface: compute the intrinsic distance with respect
#                             to this interface
#     :param str symmetry: force calculation using this symmetry, if
#                             availabe (e.g. 'generic', 'planar', 'spherical')
#                             If 'default', uses the symmetry selected in
#                             the PYTIM interface instance.
# 
#     Example:
# 
#     >>> import MDAnalysis as mda
#     >>> import pytim
#     >>> import numpy as np
#     >>> from pytim import observables
#     >>> from pytim.datafiles import MICELLE_PDB
#     >>> u = mda.Universe(MICELLE_PDB)
#     >>> micelle = u.select_atoms('resname DPC')
#     >>> waterox = u.select_atoms('type O and resname SOL')
#     >>> inter = pytim.GITIM(u,group=micelle, molecular=False, alpha=2.0)
#     >>> dist  = observables.IntrinsicDistance(interface=inter)
#     >>> d = dist.compute(waterox)
#     >>> np.set_printoptions(precision=3,threshold=10)
#     >>> print(d)
#     [25.733  8.579  8.852 ... 18.566 13.709  9.876]
# 
#     >>> np.set_printoptions(precision=None,threshold=None)
#     """
# 
#     def __init__(self, interface, symmetry='default', mode='default'):
#         Observable.__init__(self, interface.universe)
#         self.interface = interface
#         self.mode = mode
#         if symmetry == 'default':
#             self.symmetry = self.interface.symmetry
#         else:
#             self.symmetry = symmetry
# 
#     def compute(self, inp, kargs=None):
#         """Compute the intrinsic distance of a set of points from the first
#         layers.
# 
#         :param ndarray positions: compute the intrinsic distance for this set
#                                   of points
#         """
#         # see pytim/surface.py
#         return self.interface._surfaces[0].distance(inp, self.symmetry, mode=self.mode)


from .basic_observables import Number
from .intrinsic_distance import IntrinsicDistance
from scipy import stats
from MDAnalysis.core.groups import Atom, AtomGroup, Residue, ResidueGroup
import numpy as np
            size2 = 10 * len(group.universe.atoms)
            size = np.max([size1, size2])
        rnd = np.random.random((size, 3))
        rnd *= self.interface.universe.dimensions[:3]
        rnd_pos = IntrinsicDistance(
            self.interface, symmetry=self.symmetry).compute(rnd)
        rnd_accum, bins, _ = stats.binned_statistic(
            rnd_pos,
            np.ones(len(rnd_pos)),
            range=self._range,
            statistic='sum',
            bins=self._nbins)
        return rnd_accum, bins

    def sample(self, group, **kargs):
        # TODO: implement progressive averaging to handle very long trajs
        # TODO: implement memory cleanup
        if not isinstance(group, AtomGroup):
            raise TypeError("The first argument passed to "
                            "Profile.sample() must be an AtomGroup.")
        box = group.universe.trajectory.ts.dimensions[:3]
        if self._range is None:
            self._determine_range(box)
            self._determine_bins()
        v = np.prod(box)
        self._totvol.append(v)

        if self.interface is None:
            pos = group.positions[::, self._dir]
        else:

# Path: pytim/observables/basic_observables.py
# class Number(Observable):
#     """The number of atoms.
#     """
# 
#     def __init__(self, *arg, **kwarg):
#         Observable.__init__(self, None)
# 
#     def compute(self, inp, kargs=None):
#         """Compute the observable.
# 
#         :param AtomGroup inp:  the input atom group
#         :returns: one, for each atom in the group
# 
#         """
#         return np.ones(len(inp))
# 
# Path: pytim/observables/intrinsic_distance.py
# class IntrinsicDistance(Observable):
#     """Initialize the intrinsic distance calculation.
# 
#     :param PYTIM interface: compute the intrinsic distance with respect
#                             to this interface
#     :param str symmetry: force calculation using this symmetry, if
#                             availabe (e.g. 'generic', 'planar', 'spherical')
#                             If 'default', uses the symmetry selected in
#                             the PYTIM interface instance.
# 
#     Example:
# 
#     >>> import MDAnalysis as mda
#     >>> import pytim
#     >>> import numpy as np
#     >>> from pytim import observables
#     >>> from pytim.datafiles import MICELLE_PDB
#     >>> u = mda.Universe(MICELLE_PDB)
#     >>> micelle = u.select_atoms('resname DPC')
#     >>> waterox = u.select_atoms('type O and resname SOL')
#     >>> inter = pytim.GITIM(u,group=micelle, molecular=False, alpha=2.0)
#     >>> dist  = observables.IntrinsicDistance(interface=inter)
#     >>> d = dist.compute(waterox)
#     >>> np.set_printoptions(precision=3,threshold=10)
#     >>> print(d)
#     [25.733  8.579  8.852 ... 18.566 13.709  9.876]
# 
#     >>> np.set_printoptions(precision=None,threshold=None)
#     """
# 
#     def __init__(self, interface, symmetry='default', mode='default'):
#         Observable.__init__(self, interface.universe)
#         self.interface = interface
#         self.mode = mode
#         if symmetry == 'default':
#             self.symmetry = self.interface.symmetry
#         else:
#             self.symmetry = symmetry
# 
#     def compute(self, inp, kargs=None):
#         """Compute the intrinsic distance of a set of points from the first
#         layers.
# 
#         :param ndarray positions: compute the intrinsic distance for this set
#                                   of points
#         """
#         # see pytim/surface.py
#         return self.interface._surfaces[0].distance(inp, self.symmetry, mode=self.mode)


# Path: pytim/observables/profile.py
from .basic_observables import Number
from .intrinsic_distance import IntrinsicDistance
from scipy import stats
from MDAnalysis.core.groups import Atom, AtomGroup, Residue, ResidueGroup
import numpy as np

            size2 = 10 * len(group.universe.atoms)
            size = np.max([size1, size2])
        rnd = np.random.random((size, 3))
        rnd *= self.interface.universe.dimensions[:3]
        rnd_pos = IntrinsicDistance(
            self.interface, symmetry=self.symmetry).compute(rnd)
        rnd_accum, bins, _ = stats.binned_statistic(
            rnd_pos,
            np.ones(len(rnd_pos)),
            range=self._range,
            statistic='sum',
            bins=self._nbins)
        return rnd_accum, bins

    def sample(self, group, **kargs):
        # TODO: implement progressive averaging to handle very long trajs
        # TODO: implement memory cleanup
        if not isinstance(group, AtomGroup):
            raise TypeError("The first argument passed to "
                            "Profile.sample() must be an AtomGroup.")
        box = group.universe.trajectory.ts.dimensions[:3]
        if self._range is None:
            self._determine_range(box)
            self._determine_bins()
        v = np.prod(box)
        self._totvol.append(v)

        if self.interface is None:
            pos = group.positions[::, self._dir]
        else:

            pos = IntrinsicDistance(