view tvii/dataset/circle.py @ 87:9d5a5e9f5c3b

add kmeans + dataset
author Jeff Hammel <k0scist@gmail.com>
date Sun, 17 Dec 2017 14:05:57 -0800
parents
children 596dac7f3e98
line wrap: on
line source

#!/usr/bin/env python

"""
random points in a circle
"""
# TODO: a `D`-sphere

import math
import random
import sys
from .cli import DatasetGenerationParser


class CircularRandom(object):

    twopi = 2.*math.pi

    def __init__(self, center, radius=1.):
        """
        center -- (x,y) center of circle
        """

        assert radius > 0
        self.center = (x, y) = center
        self.radius = radius

    def __call__(self, n_points):
        """samples `n_points`"""

        return [self.point() for _ in xrange(n_points)]

    def point(self):
        """samples a single point"""
        # TODO: because area grows as 1/r, this will bias
        # points towards the center. This should be corrected

        r = self.radius*random.random()
        theta = self.twopi*random.random()
        x = math.cos(theta)
        y = math.sqrt(1. - x*x)
        if theta > math.pi:
            y = -y
        return (self.center[0] + x*r,
                self.center[1] + y*r)


def main(args=sys.argv[1:]):
    """CLI"""

    # parse command line
    parser = DatasetGenerationParser(description=__doc__)
    parser.add_argument('--center', dest='center',
                        nargs=2, metavar=('X', 'Y'),
                        type=float, default=(0., 0.),
                        help="center of circle [DEFAULT: %(default)s]")
    parser.add_argument('-R', '--radius', dest='radius',
                        type=float, default=1.,
                        help="radius of circle [DEFAULT: %(default)s]")
    options = parser.parse_args(args)

    # instantiate sampler
    circle = CircularRandom(options.center, options.radius)

    # get writer
    writer = parser.writer()

    # sample
    points = circle(options.number)

    # output
    writer.writerows(points)

if __name__ == '__main__':
    main()