bpf.py :  » Media-Sound-Audio » athenaCL » athenaCL » libATH » omde » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Media Sound Audio » athenaCL 
athenaCL » athenaCL » libATH » omde » bpf.py
#-----------------------------------------------------------------||||||||||||--
# Name:         bpf.py
# Purpose:      break point functions
#
# Authors:      Maurizio Umberto Puxeddu
#               Christopher Ariza
#
# Copyright:    (c) 2007 Christopher Ariza
#               (c) 2000-2001, Maurizio Umberto Puxeddu
# License:      GPL
#-----------------------------------------------------------------||||||||||||--


import math

from athenaCL.libATH.omde.functional import Function,FunctionModel


#-----------------------------------------------------------------||||||||||||--
# base class used for all varieties

class BPF(Function):
    """
    BPF(pairs)
    base class for all break-point functions
    """
    def __init__(self, pairs, periodic=0):
        """
        Return a BPF instance.

        pair is the list of pairs (time, value).
        At lease the pairs should be passed, otherwise
        a ValueError exception is raised.

        if periodic is true the periodic version of
        the call operator is used.
        if periodic is false the aperiodic version of
        the call operator is used.
        """
        Function.__init__(self)
        self.pairs = [(float(x), float(y)) for x,y in pairs]

        self._check_pairs()

        if len(self.pairs) < 2:
            raise ValueError, 'Two few pairs (%d)' % len(self.pairs)

        self.xStart, junk = self.pairs[0] # x value of first
        self.xEnd, junk = self.pairs[-1] # x value of last
        self.period = self.xEnd - self.xStart 

        if periodic:
            self.__call__ = self._evaluate_periodic
        else:
            self.__call__ = self._evaluate_aperiodic

    def _evaluate_aperiodic(self, t):
        """
        Aperiodic version of the __call__ operator.
        Values outside the boundaries of the function
        are the same of the boundaries.
        """
        (time0, value0) = self.pairs[0]
        
        # Evaluation before first point
        if t < time0:
            return value0

        index = 0 # need to check if after last point
        for (time1, value1) in self.pairs:
            if t < time1: break
            index = index + 1
            time0, value0 = time1, value1

        # Evaluation past last point
        if index == len(self.pairs):
            return value0

        return self.interpolate(t, time0, value0, time1, value1)

    def _evaluate_periodic(self, t):
        """
        Periodic version of the __call__ operator.
        Function repeats outside of the boundaries.
        """

        while t < self.xStart: # shift time to a value within the range
            t = t + self.period
        while t >= self.xEnd: 
            t = t - self.period # 
#         while t < 0: # shift 
#             t = t + self.period
#         # changed to >= rather than >
#         # > caused divide by 0 error
#         while t >= self.period: 
#             t = t - self.period # 

        for (time1, value1) in self.pairs: # find next set of points
            if t < time1: break
            time0, value0 = time1, value1

        return self.interpolate(t, time0, value0, time1, value1)
    
    def interpolate(self, time, time0, value0, time1, value1):
        """
        Interpolate the function value between two given points.
        Unimplemented method.
        """
        raise NotImplementedError

    def normalize(self):
        """
        Normalize the function in the [-1,1] range.
        """
        max = None
        min = None
        for t, v in self.pairs:
            if max == None or v > max:
                max = v
            if min == None or v < min:
                min = v
                
        if max == None or min == None:
            return
        
        factor = max - min
        new_pairs = []
        for t, v in self.pairs:
            v = (v - min) / factor
            new_pairs.append((t, v))

        self.pairs = new_pairs

    def _check_pairs(self):
        time0 = None
        for time1, value1 in self.pairs:
            if time0 is not None and time1 < time0:
                raise ValueError, 'pairs are not in temporal sequence'
            time0 = time1
            

#-----------------------------------------------------------------||||||||||||--
# note: these were all chaged such that pairs are provided as a list of lists
# this allows a list of pairs to be provided as a single object

class PowerSegment(BPF):
    """
    Break-point function with exponential interpolation.
    See the BPF base class for more info.    
    """
    def __init__(self, pairs, **dict):
        """
        Return a PowerSegment instance.
        Syntax:
        PowerSegment(...points... [, exp=1.0] [, periodic=0])
        Break-points are specified as couples
        (time, value)
        like PowerSegment((0, 1), (5, 3), (20, 1))
        """
        if dict.has_key('exp'):
            self.exponent = dict['exp']
        else: self.exponent = 1.0

        if dict.has_key('periodic'):
            periodic = dict['periodic']
        else: periodic = 0

        BPF.__init__(self, pairs, periodic)

    def interpolate(self, time, time0, value0, time1, value1):
        r = (time - time0)/(time1 - time0)

        if value1 == value0:
            return value0
        elif self.exponent == 0.0:
            return value0 + r * (value1 - value0)
        elif self.exponent > 0.0:
            if value1 >= value0:
                return value0 + pow(r, 1.0 + self.exponent) * (value1 - value0)
            else:
                return value1 + (pow(1.0 - r, 1.0 + self.exponent) * 
                                (value0 - value1))
        else:
            if value1 >= value0:
                return value1 + (pow(1.0 - r, 1.0 - self.exponent) * 
                                (value0 - value1))
            else:
                return value0 + pow(r, 1.0 - self.exponent) * (value1 - value0)


class LinearSegment(BPF):
    """
    Break-point function with linear interpolation.
    See the BPF base class for more info.    
    """
    def __init__(self, pairs, **dict):
        """
        Return a LinearSegment instance.
        Syntax:
        LinearSegment(...points... [, exp=1.0] [, periodic=0])
        Break-points are specified as couples
        (time, value)
        like LineSegment((0, 1), (5, 3), (20, 1))
        """
        if dict.has_key('periodic'):
            periodic = dict['periodic']
        else: periodic = 0
        BPF.__init__(self, pairs, periodic)
        
    def interpolate(self, time, time0, value0, time1, value1):
        return value0 + ((time - time0)/(time1 - time0)) * (value1 - value0)



class HalfCosineSegment(BPF):
    """
    Break-point function with half-cosine interpolation.
    See the BPF base class for more info. 
    """
    def __init__(self, pairs, **dict):
        if dict.has_key('periodic'):
            periodic = dict['periodic']
        else: periodic = 0
        BPF.__init__(self, pairs, periodic)
        
    def interpolate(self, time, time0, value0, time1, value1):
        x = ((time - time0) / (time1 - time0)) * math.pi + math.pi
        return value0 + ((value1 - value0) * (1 + math.cos(x)) / 2.0)



class NoInterpolationSegment(BPF):
    """
    Break-point function without interpolation.
    See the BPF base class for more info.
    """
    def __init__(self, pairs, **dict):
        """
        Return a NoInterpolationSegment instance.
        Syntax:
        NoInterpolationSegment(...points... [, exp=...])
        Break-point function without interpolation.
        Break-points are specified as couples
        (time, value)
        like NoInterpolationSegment((0, 1), (5, 3), (20, 1))
        """
        if dict.has_key('periodic'):
            periodic = dict['periodic']
        else: periodic = 0
        BPF.__init__(self, pairs, periodic)

    def interpolate(self, time, time0, value0, time1, value1):
        return value0











#-----------------------------------------------------------------||||||||||||--
if __name__ == '__main__':
    segment1 = HalfCosineSegment((0.0, 0.0), (4.0, 10.0), (7.0, 5.0), 
                                 (9.0, 8.0))
    segment2 = NoInterpolationSegment((0.0, 0.0), (4.0, 10.0), (7.0, 5.0), 
                                       (9.0, 8.0))
    segment3 = PowerSegment((0.0, 0.0), (4.0, 10.0), (7.0, 5.0), 
                           (9.0, 8.0), exp=0.5)
    segment4 = PowerSegment((0.0, 0.0), (4.0, 10.0), (7.0, 5.0), 
                           (9.0, 8.0), exp=2.0)
    segment5 = PowerSegment((0.0, 0.0), (4.0, 10.0), (7.0, 5.0), 
                           (9.0, 8.0), exp=-0.5)
    segment6 = PowerSegment((0.0, 0.0), (4.0, 10.0), (7.0, 5.0), 
                           (9.0, 8.0), exp=-2.0)
    segment7 = LinearSegment((0.0, 0.0), (4.0, 10.0), (7.0, 5.0), (9.0, 8.0))
    
    t = 0.0
    step = 0.01
    for i in range(1200):
        print (t, segment1(t), segment2(t), segment3(t), segment4(t),
               segment5(t), segment6(t), segment7(t))
        t = t + step
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.