"""Read SIFT and SURF feature files.

See Also
--------
http://people.cs.ubc.ca/~lowe/keypoints/
http://www.vision.ee.ethz.ch/~surf/
"""

__all__ = ['load_sift', 'load_surf']

import numpy as np


def _sift_read(f, mode='SIFT'):
    """Read SIFT or SURF features from a file.

    Parameters
    ----------
    f : string or open file
        Input file generated by the feature detectors from
        http://people.cs.ubc.ca/~lowe/keypoints/ or
        http://www.vision.ee.ethz.ch/~surf/

    Returns
    -------
    data : record array with fields
      - row: int
          row position of feature
      - column: int
          column position of feature
      - scale: float
          feature scale
      - orientation: float
          feature orientation
      - data: array
          feature values

    """
    if not hasattr(f, 'readline'):
        f = file(f, 'r')

    if mode == 'SIFT':
        nr_features, feature_len = map(int, f.readline().split())
        datatype = np.dtype([('row', float), ('column', float),
                            ('scale', float), ('orientation', float),
                            ('data', (float, feature_len))])
    else:
        mode = 'SURF'
        feature_len = int(f.readline()) - 1
        nr_features = int(f.readline())
        datatype = np.dtype([('column', float), ('row', float),
                            ('second_moment', (float, 3)),
                            ('sign', float), ('data', (float, feature_len))])
    data = np.fromfile(f, sep=' ')
    if data.size != nr_features * datatype.itemsize / np.dtype(float).itemsize:
        raise IOError("Invalid %s feature file." % mode)

    return data.view(datatype)


def load_sift(f):
    return _sift_read(f, mode='SIFT')


def load_surf(f):
    return _sift_read(f, mode='SURF')

load_sift.__doc__ = _sift_read.__doc__
load_surf.__doc__ = _sift_read.__doc__
