# $CVSHeader: pal8e/src/Bin.py,v 1.2 2005/02/15 01:10:24 indraneel Rel $

# bins data in a dict with class mark as key
# optional start and end points
# bin_size is required
# good only to 2 places of decimal

import Numeric

class Bin(dict):
    def __init__(self, data):
        self.data = data
        self.start = min(data)
        self.end = max(data)

    def __setLimits(self, start, end):
        self.start = start
        self.end = end

    def bin(self, bin_size, start=None, end=None):
        bin_size = float(bin_size)
        if start!=None: start = float(start)
        if end!=None: end = float(end)
        if ((start!=None) and (end!=None)):
            self.__setLimits(start, end)
        for d in self.data:
            if (d < self.start) or (d > self.end): continue
            x = int((d - self.start)/bin_size)
            class_mark = (x * bin_size) + self.start + (bin_size/2)
            class_mark = '%07.3f' % class_mark
            if self.has_key(class_mark):
                self[class_mark] += 1
            else: self[class_mark] = 1
        # fill up empty class marks
        if start!=None: i = '%07.3f' % (start+(bin_size/2))
        else: i = min(self.keys())
        if end!=None: last_key = '%07.3f' % end
        else: last_key = max(self.keys())
        while float(i) <= float(last_key):
            if not self.has_key(i):
                self[i] = 0
            i = '%07.3f' % (float(i)+bin_size)

    def normalise(self):
        points = sum(self.values())
        for k in self.keys():
            #print k, '\t', self[k]/float(points)
            self[k] = '%.3f' % (self[k]/float(points))

    def getNumarray(self):
        kys = self.keys()
        for i,k in enumerate(kys):
            kys[i] = float(k)
        kys.sort()
        v=[]
        for k in kys:
            k = '%07.3f' % k
            v.append(float(self[k]))
        k=[]
        for i in kys:
            k.append(float(i))
        ary = Numeric.transpose((k, v))
        return ary
