# Path: pytim/observables/basic_observables.py
# class Position(Vector):
#     """ Atomic positions
# 
#         Example: compute the projection on the xz plane of the first water molecule
# 
#         >>> import MDAnalysis as mda
#         >>> import pytim
#         >>> u = mda.Universe(pytim.datafiles.WATER_GRO)
#         >>> proj = pytim.observables.Position('xz')
#         >>> with np.printoptions(precision=3):
#         ...     print(proj.compute(u.residues[0].atoms) )
#         [[28.62 11.37]
#          [28.42 10.51]
#          [29.61 11.51]]
# 
#     """
#     # TODO: add a flag to prevent recomputing the reference frame, in case
#     # it's constant
# 
#     def __init__(self, arg='xyz', **kwarg):
#         Vector.__init__(self, arg, kwarg)
#         try:
#             self.folded = kwarg['folded']
#         except KeyError:
#             self.folded = True
#         try:
#             self.cartesian = kwarg['cartesian']
#         except KeyError:
#             self.cartesian = True
#         try:
#             self.spherical = kwarg['spherical']
#         except KeyError:
#             self.spherical = False
# 
#         if self.spherical is True:
#             self.cartesian = False
# 
#     def _cartesian_to_spherical(self, cartesian):
#         spherical = np.empty(cartesian.shape)
#         spherical[:, 0] = np.linalg.norm(cartesian, axis=1)
#         if len(self.dirmask) > 1:  # 2d or 3d
#             spherical[:, 1] = np.arctan2(cartesian[:, 1], cartesian[:, 0])
#         if len(self.dirmask) == 3:  # 3d
#             xy = np.sum(cartesian[:, [0, 1]]**2, axis=1)
#             spherical[:, 2] = np.arctan2(np.sqrt(xy), cartesian[:, 2])
# 
#         return spherical
# 
#     def compute(self, inp, **kwarg):
#         """Compute the observable.
# 
#         :param AtomGroup inp:  the input atom group
#         :returns: atomic positions
# 
#         """
#         inp = self._to_atomgroup(inp)
#         box = inp.universe.dimensions[:3]
#         if self.folded:
#             cartesian = inp.atoms.pack_into_box()
#            # return cartesian[:,self.dirmask]
#         else:
#             cartesian = inp.positions
# 
#         if self.cartesian:
#             return cartesian[:, self.dirmask]
#         if self.spherical:
#             return self._cartesian_to_spherical(cartesian)[:, self.dirmask]
# 
# class RelativePosition(Position):
# 
#     def __init__(self, arg='xyz', **kwarg):
#         return Position.__init__(self, arg, **kwarg)
# 
#     def compute(self, inp1, inp2, reference_frame=None):
#         # by adding a new axis we allow take the difference of positions
#         # of the N inp atoms to the M reference_group ones.
#         # pos here has dimension (N,M,3)
# 
#         inp1 = self._to_atomgroup(inp1)
#         inp2 = self._to_atomgroup(inp2)
#         pos = inp1.positions[:, np.newaxis] - inp2.positions
#         if reference_frame is True:
#             ref = ReferenceFrame().compute(inp2)
#             pos = 0
#         elif reference_frame is not None:
#             try:
#                 ref = ReferenceFrame().compute(reference_frame)
#                 pos = 0
#             except:
#                 raise ValueError(
#                     'reference_frame can be None,True, or an atom group ')
# 
#         # let's get back to dimension (NxM,dimension)
#         pos = pos[:, :, self.dirmask]
#         dimension = len(self.dirmask)
#         pos = pos.reshape((np.prod(pos.shape[:-1]), dimension))
#         box = inp1.universe.dimensions[self.dirmask]
#         if self.folded:
#             cond = np.where(pos > box / 2.)
#             pos[cond] -= box[cond[1]]
#             cond = np.where(pos < -box / 2.)
#             pos[cond] += box[cond[1]]
# 
#         if self.cartesian:
#             return pos
#         if self.spherical:
#             return self._cartesian_to_spherical(pos)


import numpy as np
from . import Position, RelativePosition

        self.dimensions = np.asarray(self.coords_in).shape[0]
        self.dimensions_out = np.asarray(self.coords_out).shape[0]
        self.generalized_coordinate = generalized_coordinate

        self.cartesian = np.any(
            [coord in self.cartesian_coords for coord in self.coords_out])
        self.spherical = np.any(
            [coord in self.spherical_coords for coord in self.coords_out])

        if (self.cartesian and self.spherical) or (not self.cartesian and not self.spherical):
            raise ValueError("Can pass either any of Cartesian ['x','y','z'] \
                                or of spherical ['r','phi','theta'] coordinates ")
        if self.spherical:
            all_coords = self.spherical_coords
        if self.cartesian:
            all_coords = self.cartesian_coords

        self.dirmask_out = np.array(
            [np.where(np.asarray(all_coords) == c)[0][0] for c in self.coords_out])

        if self.generalized_coordinate is None:
            if self.order == 1:
                self.generalized_coordinate = Position(self.coords_in, cartesian=self.cartesian,
                                                       spherical=self.spherical)
            if self.order == 2:
                self.generalized_coordinate = RelativePosition(self.coords_in, cartesian=self.cartesian,
                                                               spherical=self.spherical)

        if max_distance is None:

# Path: pytim/observables/basic_observables.py
# class Position(Vector):
#     """ Atomic positions
# 
#         Example: compute the projection on the xz plane of the first water molecule
# 
#         >>> import MDAnalysis as mda
#         >>> import pytim
#         >>> u = mda.Universe(pytim.datafiles.WATER_GRO)
#         >>> proj = pytim.observables.Position('xz')
#         >>> with np.printoptions(precision=3):
#         ...     print(proj.compute(u.residues[0].atoms) )
#         [[28.62 11.37]
#          [28.42 10.51]
#          [29.61 11.51]]
# 
#     """
#     # TODO: add a flag to prevent recomputing the reference frame, in case
#     # it's constant
# 
#     def __init__(self, arg='xyz', **kwarg):
#         Vector.__init__(self, arg, kwarg)
#         try:
#             self.folded = kwarg['folded']
#         except KeyError:
#             self.folded = True
#         try:
#             self.cartesian = kwarg['cartesian']
#         except KeyError:
#             self.cartesian = True
#         try:
#             self.spherical = kwarg['spherical']
#         except KeyError:
#             self.spherical = False
# 
#         if self.spherical is True:
#             self.cartesian = False
# 
#     def _cartesian_to_spherical(self, cartesian):
#         spherical = np.empty(cartesian.shape)
#         spherical[:, 0] = np.linalg.norm(cartesian, axis=1)
#         if len(self.dirmask) > 1:  # 2d or 3d
#             spherical[:, 1] = np.arctan2(cartesian[:, 1], cartesian[:, 0])
#         if len(self.dirmask) == 3:  # 3d
#             xy = np.sum(cartesian[:, [0, 1]]**2, axis=1)
#             spherical[:, 2] = np.arctan2(np.sqrt(xy), cartesian[:, 2])
# 
#         return spherical
# 
#     def compute(self, inp, **kwarg):
#         """Compute the observable.
# 
#         :param AtomGroup inp:  the input atom group
#         :returns: atomic positions
# 
#         """
#         inp = self._to_atomgroup(inp)
#         box = inp.universe.dimensions[:3]
#         if self.folded:
#             cartesian = inp.atoms.pack_into_box()
#            # return cartesian[:,self.dirmask]
#         else:
#             cartesian = inp.positions
# 
#         if self.cartesian:
#             return cartesian[:, self.dirmask]
#         if self.spherical:
#             return self._cartesian_to_spherical(cartesian)[:, self.dirmask]
# 
# class RelativePosition(Position):
# 
#     def __init__(self, arg='xyz', **kwarg):
#         return Position.__init__(self, arg, **kwarg)
# 
#     def compute(self, inp1, inp2, reference_frame=None):
#         # by adding a new axis we allow take the difference of positions
#         # of the N inp atoms to the M reference_group ones.
#         # pos here has dimension (N,M,3)
# 
#         inp1 = self._to_atomgroup(inp1)
#         inp2 = self._to_atomgroup(inp2)
#         pos = inp1.positions[:, np.newaxis] - inp2.positions
#         if reference_frame is True:
#             ref = ReferenceFrame().compute(inp2)
#             pos = 0
#         elif reference_frame is not None:
#             try:
#                 ref = ReferenceFrame().compute(reference_frame)
#                 pos = 0
#             except:
#                 raise ValueError(
#                     'reference_frame can be None,True, or an atom group ')
# 
#         # let's get back to dimension (NxM,dimension)
#         pos = pos[:, :, self.dirmask]
#         dimension = len(self.dirmask)
#         pos = pos.reshape((np.prod(pos.shape[:-1]), dimension))
#         box = inp1.universe.dimensions[self.dirmask]
#         if self.folded:
#             cond = np.where(pos > box / 2.)
#             pos[cond] -= box[cond[1]]
#             cond = np.where(pos < -box / 2.)
#             pos[cond] += box[cond[1]]
# 
#         if self.cartesian:
#             return pos
#         if self.spherical:
#             return self._cartesian_to_spherical(pos)


# Path: pytim/observables/distributionfunction.py
import numpy as np
from . import Position, RelativePosition


        self.dimensions = np.asarray(self.coords_in).shape[0]
        self.dimensions_out = np.asarray(self.coords_out).shape[0]
        self.generalized_coordinate = generalized_coordinate

        self.cartesian = np.any(
            [coord in self.cartesian_coords for coord in self.coords_out])
        self.spherical = np.any(
            [coord in self.spherical_coords for coord in self.coords_out])

        if (self.cartesian and self.spherical) or (not self.cartesian and not self.spherical):
            raise ValueError("Can pass either any of Cartesian ['x','y','z'] \
                                or of spherical ['r','phi','theta'] coordinates ")
        if self.spherical:
            all_coords = self.spherical_coords
        if self.cartesian:
            all_coords = self.cartesian_coords

        self.dirmask_out = np.array(
            [np.where(np.asarray(all_coords) == c)[0][0] for c in self.coords_out])

        if self.generalized_coordinate is None:
            if self.order == 1:
                self.generalized_coordinate = Position(self.coords_in, cartesian=self.cartesian,
                                                       spherical=self.spherical)
            if self.order == 2:
                self.generalized_coordinate = RelativePosition(self.coords_in, cartesian=self.cartesian,
                                                               spherical=self.spherical)

        if max_distance is None:

            if (isinstance(self.generalized_coordinate, Position) or