<commit_before>import numpy as N
from attributes import readonly

valid = ('xspace', 'yspace', 'zspace', 'time', 'vector_dimension', 'concat')
space = ('zspace', 'yspace', 'xspace')
spacetime = ('time', 'zspace', 'yspace', 'xspace')


class Axis (object):
    """
    This class represents a generic axis. Axes are used in the definition
    of CoordinateSystem.
    """
    class name (readonly): "dimension name"; implements=str

    def __init__(self, name, values=None):
        self.name = name
        if self.name not in valid:
            raise ValueError, 'recognized dimension names are ' + `valid`
        if values is None:
            self._values = []
        else:
            self._values = values
        self.length = len(self._values)

    def values(self):
        return self._values

    def __eq__(self, axis):
        "Equality is defined by name and values."
        return hasattr(axis,"name") and \
               self.name == axis.name and \
               self.length == axis.length and \
               N.all(N.equal(self.values(), axis.values()))
    
    def __len__(self):
        return self.length

class RegularAxis (Axis):
    """
    This class represents a regularly spaced axis. Axes are used in the
    definition of Coordinate systems. The attributes step and start are usually
    ignored if a valid transformation matrix is provided -- otherwise they
    can be used to create an orthogonal transformation matrix.

    >>> from neuroimaging.reference.axis import RegularAxis
    >>> from numpy import allclose, array
    >>> r = RegularAxis(name='xspace',length=10, start=0.25, step=0.3)
    >>> allclose(r.values(), array([ 0.25,  0.55,  0.85,  1.15,  1.45,  1.75,  2.05,  2.35,  2.65,  2.95]))
    True
    >>>
    """

    def __init__(self, name, length=0, start=0, step=0):
        _values = N.linspace(start, start + step*length, length, False)
        Axis.__init__(self, name, _values)
        self.start = start
        self.step = step


class VoxelAxis (RegularAxis):
    "An axis with a length as well."

    def __init__(self, name, length=0):
        RegularAxis.__init__(self, name, length, start=0, step=1)


# Default axes
generic = (
  Axis(name='zspace'),
  Axis(name='yspace'),
  Axis(name='xspace'))

   

if __name__ == "__main__":
    import doctest
    doctest.testmod()
<commit_msg>modifications to the Axis class structure to allow for infinite axes<commit_after>"""
The Axis family of classes are used to represent a named axis within a
coordinate system. Axes can be discrete or continuous, finite or infinite.

The current class hirachy looks like this.

                 Axis
                   |
        ---------------------------
        |                         |
        DiscreteAxis        ContinuousAxis
        |   
   RegularAxis
        |
   VoxelAxis


There is currently no support for irregularly spaced axes, however this
could easily be added as a subclass of DiscreteAxis if required.

"""

import numpy as N
from attributes import readonly

valid = ('xspace', 'yspace', 'zspace', 'time', 'vector_dimension', 'concat')
space = ('zspace', 'yspace', 'xspace')
spacetime = ('time', 'zspace', 'yspace', 'xspace')

class Axis(object):
    """
    This class represents a generic axis. Axes are used in the definition
    of CoordinateSystem.
    """

    class name(readonly):
        "axis name"
        implements = str

    def __init__(self, name):
        self.name = name
        if self.name not in valid:
            raise ValueError, 'recognized dimension names are ' + `valid`

    def __eq__(self, other):
        return self.name == other.name

    def valid(self, x):
        """ test if x is a point on the axis. """
        raise NotImplementedError

    def max(self):
        raise NotImplementedError

    def min(self):
        raise NotImplementedError

    def range(self):
        return (self.min(), self.max())


class ContinuousAxis(Axis):
    def __init__(self, name, low=-N.inf, high=N.inf):
        self.low = low
        self.high = high
        Axis.__init__(self, name)

    def __eq__(self, other):
        return self.range() == other.range() and \
               Axis.__eq__(self, other)

    def valid(self, x):
        """ The axis is defined as the range [low:high) """
        return self.low <= x < self.high

    def max(self):
        return self.high

    def min(self):
        return self.low


class DiscreteAxis(Axis):

    def __init__(self, name):
        Axis.__init__(self, name)

    def valid(self, x):
        raise NotImplementedError

    def min(self):
        raise NotImplementedError

    def max(self):
        raise NotImplementedError

    def values(self):
        """
        Return all the values in the axis.
        Return a generator for the infinite case
        """
        raise NotImplementedError
            
class RegularAxis (DiscreteAxis):
    """
    This class represents a regularly spaced axis. Axes are used in the
    definition of Coordinate systems. The attributes step and start are usually
    ignored if a valid transformation matrix is provided -- otherwise they
    can be used to create an orthogonal transformation matrix.

    >>> from neuroimaging.reference.axis import RegularAxis
    >>> from numpy import allclose, array
    >>> r = RegularAxis(name='xspace',length=10, start=0.25, step=0.3)
    >>> allclose(r.values(), array([ 0.25,  0.55,  0.85,  1.15,  1.45,  1.75,  2.05,  2.35,  2.65,  2.95]))
    True
    >>>
    """

    def __init__(self, name, length=N.inf, start=0, step=1):
        self.length = length
        self.start = start
        self.step = step        
        DiscreteAxis.__init__(self, name)

    def __eq__(self, other):        
        return self.length == other.length and \
               self.start == other.start and \
               self.step == other.step and \
               DiscreteAxis.__eq__(self, other)

    def valid(self, x):
        if x in (-N.inf, N.inf):
            return False
        if self.length == N.inf:
            tmp = (x - self.start)/self.step
            return (tmp == int(tmp)) and (0 <= tmp < self.length)
        else:
            return x in self.values()

    def values(self):
        if self.length == N.inf:
            def f(x):
                while True:
                    yield x
                    x += self.step
            return f(self.start)
        else:
            return N.linspace(self.min(), self.max() + self.step, self.length, False)

    def max(self):
        return self.start + self.step*(self.length - 1)

    def min(self):
        return self.start

class VoxelAxis (RegularAxis):
    """
    A RegularAxis which starts at 0 and has a step of 1.
    """
    def __init__(self, name, length=N.inf):
        RegularAxis.__init__(self, name, length, start=0, step=1)


# Default axes
generic = (
  ContinuousAxis(name='zspace'),
  ContinuousAxis(name='yspace'),
  ContinuousAxis(name='xspace'))

   


{'fraction_non_alphanumeric': 0.1148997134670487, 'fraction_numerical': 0.012607449856733524, 'mean_word_length': 2.209655172413793, 'pattern_counts': {'":': 1, '<': 7, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4649783', 'n_tokens_mistral': 2091, 'n_tokens_neox': 1988, 'n_words': 664}