[Nipy-devel] Axis and friends
Jonathan Taylor
jonathan.taylor at stanford.edu
Tue Jul 11 13:40:07 CDT 2006
I have no objection -- sorry didn't reply this weekend...
-- Jonathan
Tim Leslie wrote:
> On 7/11/06, Karl Young <Karl.Young at ucsf.edu> wrote:
>
>> At the level of class definitions in the basic infrastructure I'm more
>> of a user than a developer but these changes look good to me (unless
>> Jonathan or anyone else had specific reasons for the bottom up version),
>> and they are easy to parse.
>>
>
> Well, I've got one reply in support and none against, so I'll check
> these in tonight. We can always revert if we decide to stick with the
> old design.
>
> The other significant change I'd like to make to the reference package
> is to add a separate mni.py module to handle the MNI specific stuff
> (MNI, MNI_voxel, MNI_world, etc). These had been scattered through
> various other modules and I think they deserve a home of their own.
> When looking through the various reference modules, these particular
> instances would be tacked on at the end, and IMHO looked a little out
> of place. Only when you realise that they all come together as a
> single collection of references do they begin to make sense. By having
> a separate MNI module, these instances are all grouped together, so
> it's easy to see how the MNI reference world is constructed, without
> polluting the modules which actually do the hard work.
>
> Since the axis changes and the mni changes are all kinda squished
> together in my svn tree, I'd like to check them all in at once. I'll
> do this at the end of the night unless anyone raises an object and of
> course Jonathon, if you don't like some of these changes we can always
> change them back.
>
> Cheers,
>
> Tim
>
>
>>> Hi All,
>>>
>>> I was looking at reference/axis.py today and thinking about the class
>>> structure. At present, we have Axis, which just has a name, then we
>>> derive from the VoxelAxis, which also has a length and a set of
>>> values(), we then derive RegularAxis which adds a start and step
>>> parameter. In essence, we are creating subclasses to _extend_ the base
>>> class. We start off with the bare bones Axis class and add on the new
>>> features at each level.
>>>
>>> The other way to approach this design is to have the base class (Axis)
>>> provide the full interface (values, length, name) and then have each
>>> of the base classes _specialise_ this class. So an Axis can have any
>>> set of values it wants, a RegularAxis has values which are regularly
>>> spaced with a given start and step, and a VoxelAxis is a RegularAxis
>>> where start = 0 and step = 1.
>>>
>>> The advantages to this kind of arrangement is that there is a single
>>> interface which the external users have to know about, and the
>>> implementation of each of these classes becomes easier.
>>>
>>> I've implemented this different arrangement to show what I mean. I was
>>> hoping to hear other peoples thoughts on this design choice. My new
>>> version of axis.py passes all the tests, so we don't have to worry
>>> about breaking existing. The new version cuts the line count from 114
>>> down to 81 and IMHO is a lot easier to read.
>>>
>>> What do other people think?
>>>
>>> Cheers,
>>>
>>> Tim
>>>
>>> ------------------------------------------------------------------------
>>>
>>> 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 Coordinate system. 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'))
>>>
>>> # MNI template axes
>>> MNI = (
>>> RegularAxis(name='zspace', length=109, start=-72., step=2.0),
>>> RegularAxis(name='yspace', length=109, start=-126., step=2.0),
>>> RegularAxis(name='xspace', length=91, start=-90., step=2.0))
>>>
>>>
>>> if __name__ == "__main__":
>>> import doctest
>>> doctest.testmod()
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> _______________________________________________
>>> Nipy-devel mailing list
>>> Nipy-devel at scipy.org
>>> http://projects.scipy.org/mailman/listinfo/nipy-devel
>>>
>>>
>>>
>> --
>>
>> Karl Young
>> Center for Imaging of Neurodegenerative Diseases, UCSF
>> VA Medical Center (114M) Phone: (415) 221-4810 x3114 lab
>> 4150 Clement Street FAX: (415) 668-2864
>> San Francisco, CA 94121 Email: karl young at ucsf edu
>>
>>
> _______________________________________________
> Nipy-devel mailing list
> Nipy-devel at scipy.org
> http://projects.scipy.org/mailman/listinfo/nipy-devel
>
--
------------------------------------------------------------------------
Jonathan Taylor Tel: 650.723.9230
Dept. of Statistics Fax: 650.725.8977
Sequoia Hall, 137 www-stat.stanford.edu/~jtaylo
390 Serra Mall
Stanford, CA 94305
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://projects.scipy.org/pipermail/nipy-devel/attachments/20060711/e2f30c02/attachment.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jonathan.taylor.vcf
Type: text/x-vcard
Size: 329 bytes
Desc: not available
Url : http://projects.scipy.org/pipermail/nipy-devel/attachments/20060711/e2f30c02/attachment.vcf
More information about the Nipy-devel
mailing list