예제 #1
0
def test_smooth():
    """
    Create a step profile with redundant steps, then smooth it.
    """

    profile = [(getTime("01:00:00"), 6.2), (getTime("02:00:00"), 6.2),
               (getTime("03:00:00"), 6), (getTime("04:00:00"), 6),
               (getTime("05:00:00"), 6), (getTime("06:00:00"), 5.4),
               (getTime("07:00:00"), 5.2), (getTime("08:00:00"), 5.2),
               (getTime("09:00:00"), 5.8), (getTime("10:00:00"), 6),
               (getTime("11:00:00"), 6.2), (getTime("12:00:00"), 6.2)]

    expectation = [(getTime("01:00:00"), 6.2), (getTime("03:00:00"), 6),
                   (getTime("06:00:00"), 5.4), (getTime("07:00:00"), 5.2),
                   (getTime("09:00:00"), 5.8), (getTime("10:00:00"), 6),
                   (getTime("11:00:00"), 6.2), (getTime("12:00:00"), 6.2)]

    # Create profile
    p = StepProfile()
    p.T, p.y = lib.unzip(profile)

    # Smooth it
    p.smooth()

    # No redundant steps allowed in smoothed profile
    assert [p.T, p.y] == lib.unzip(expectation)
예제 #2
0
def test_cut():
    """
    Create a profile and cut off some of its data (outside some given time
    range).
    """

    profile = [(getTime("23:30:00", "1970.01.01"), 6.2),
               (getTime("00:00:00", "1970.01.02"), 6),
               (getTime("00:30:00", "1970.01.02"), 5.8),
               (getTime("00:00:00", "1970.01.03"), 5.6),
               (getTime("00:30:00", "1970.01.03"), 5.4),
               (getTime("00:00:00", "1970.01.04"), 5.2)]

    # Create profile
    p = Profile()
    p.T, p.y = lib.unzip(profile)
    p.start = profile[1][0]
    p.end = profile[-1][0]

    # Cut it
    last = p.cut()

    # First entry should be cut off
    assert last == profile[0][1]
    assert [p.T, p.y] == lib.unzip(profile[1:])

    # Rewrite profile
    p.T, p.y = lib.unzip(profile)

    # Cut with given datetimes
    last = p.cut(profile[2][0], profile[-2][0])

    # First two entries and last one should be cut off
    assert last == profile[1][1]
    assert [p.T, p.y] == lib.unzip(profile[2:-1])
예제 #3
0
def test_op():
    """
    Create several step profiles, and do operations on them.
    """

    start, end = getTime("00:00:00"), getTime("02:00:00")

    profiles = [[(start, 6), (getTime("00:30:00"), 5.8),
                 (getTime("01:00:00"), 5.2), (getTime("01:30:00"), 5.6),
                 (end, 4.8)],
                [(start, 0.1), (getTime("00:10:00"), 3),
                 (getTime("00:35:00"), 2.8), (getTime("01:05:00"), 6.2),
                 (getTime("01:30:00"), 7.6), (end, 0.8)]]

    expectationAdd = [(start, 6.1), (getTime("00:10:00"), 9),
                      (getTime("00:30:00"), 8.8), (getTime("00:35:00"), 8.6),
                      (getTime("01:00:00"), 8), (getTime("01:05:00"), 11.4),
                      (getTime("01:30:00"), 13.2), (end, 5.6)]

    expectationSubtract = [
        (start, 5.9), (getTime("00:10:00"), 3), (getTime("00:30:00"), 2.8),
        (getTime("00:35:00"), 3), (getTime("01:00:00"), 2.4),
        (getTime("01:05:00"), -1), (getTime("01:30:00"), -2), (end, 4)
    ]

    expectationMultiply = [(start, 0.6), (getTime("00:10:00"), 18),
                           (getTime("00:30:00"), 17.4),
                           (getTime("00:35:00"), 16.24),
                           (getTime("01:00:00"), 14.56),
                           (getTime("01:05:00"), 32.24),
                           (getTime("01:30:00"), 42.56), (end, 3.84)]

    expectationDivide = [(start, 6 / 0.1), (getTime("00:10:00"), 6 / 3),
                         (getTime("00:30:00"), 5.8 / 3),
                         (getTime("00:35:00"), 5.8 / 2.8),
                         (getTime("01:00:00"), 5.2 / 2.8),
                         (getTime("01:05:00"), 5.2 / 6.2),
                         (getTime("01:30:00"), 5.6 / 7.6), (end, 4.8 / 0.8)]

    # Create profiles
    p1 = StepProfile()
    p1.T, p1.y = lib.unzip(profiles[0])
    p1.start, p1.end = start, end
    p1.norm = end

    p2 = StepProfile()
    p2.T, p2.y = lib.unzip(profiles[1])
    p2.start, p2.end = start, end
    p2.norm = end

    # Test operations on them
    do_test_op("+", p1, p2, expectationAdd)
    do_test_op("-", p1, p2, expectationSubtract)
    do_test_op("*", p1, p2, expectationMultiply)
    do_test_op("/", p1, p2, expectationDivide)
예제 #4
0
def unpackage():
    """
        Unpacking of a scene file created by the copyPastePackage.package function. this needs to be looked at.
        I don't have windows so I have no idea if it works there.
            
    """

    zipfileLoc = hou.ui.selectFile(
        title="please select a zipFile created by the package function",
        pattern="*.zip")
    if not zipfileLoc:

        return

    file_ = zipfile.ZipFile(hou.expandString(zipfileLoc), "r")

    isOke = False

    for name in file_.namelist():

        if name.endswith(".hip") or name.endswith(".hipnc"):

            isOke = True
            break

    if not isOke:

        return

    unpackLoc = hou.expandString(
        hou.ui.selectFile(
            title=
            "please select a directory you wish to use to unpack the files to."
        ))

    if not unpackLoc or not os.path.isdir(unpackLoc):

        return

    unzip(file_, unpackLoc)
    unpackageDir = os.path.dirname(file_.namelist()[0])
    otlsfiles = glob.glob(os.path.join(unpackLoc, unpackageDir, "otls", "*"))
    hipfile = glob.glob(os.path.join(unpackLoc, unpackageDir, "*.hip*"))

    if len(hipfile) != 1:

        return

    hou.hipFile.load(hipfile[0])

    for otl in otlsfiles:

        hou.hda.installFile(otl)
예제 #5
0
def unpackage():
    """
        Unpacking of a scene file created by the copyPastePackage.package function. this needs to be looked at.
        I don't have windows so I have no idea if it works there.
            
    """

    zipfileLoc = hou.ui.selectFile(title="please select a zipFile created by the package function", pattern="*.zip")
    if not zipfileLoc: 
        
        return
    
    file_ = zipfile.ZipFile(hou.expandString(zipfileLoc), "r")

    isOke = False
    
    for name in file_.namelist():
        
        if name.endswith(".hip") or name.endswith(".hipnc"):
            
            isOke = True
            break
    
    if not isOke: 
        
        return
        
    unpackLoc = hou.expandString(hou.ui.selectFile(title="please select a directory you wish to use to unpack the files to."))
    
    if not unpackLoc or not os.path.isdir(unpackLoc): 
        
        return
      
    unzip(file_, unpackLoc)
    unpackageDir = os.path.dirname(file_.namelist()[0])
    otlsfiles = glob.glob(os.path.join(unpackLoc, unpackageDir, "otls", "*"))
    hipfile = glob.glob(os.path.join(unpackLoc, unpackageDir, "*.hip*"))
        
    if len(hipfile) != 1: 
        
        return
    
    hou.hipFile.load(hipfile[0])
        
    for otl in otlsfiles:

        hou.hda.installFile(otl)
예제 #6
0
def test_pad():
    """
    Force start/end limits on profile, using (if available) the value of the
    step preceding beginning of profile.
    """

    profile = [(getTime(dateString="1970.01.02"), 6.2),
               (getTime(dateString="1970.01.03"), 6)]

    start = getTime(dateString="1970.01.01")
    end = getTime(dateString="1970.01.04")
    last = 0
    zero = 1000

    # Create empty profile
    p = StepProfile()

    # Pad it
    p.pad(start, end, last)

    assert p.T[0] == start and p.T[-1] == end
    assert p.y[0] == last and p.y[-1] == last

    # Create profile
    p = StepProfile()
    p.T, p.y = lib.unzip(profile)

    # Pad it
    p.pad(start, end, last)

    assert p.T[0] == start and p.T[-1] == end
    assert p.y[0] == last and p.y[-1] == profile[-1][1]

    # Create profile with a specific zero value
    p = StepProfile()
    p.T, p.y = lib.unzip(profile)
    p.zero = zero

    # Pad it without last value
    p.pad(start, end)

    assert p.T[0] == start and p.T[-1] == end
    assert p.y[0] == zero and p.y[-1] == profile[-1][1]
예제 #7
0
def do_test_fill(profile, fillers, expectations):
    """
    Helper function to test filling of profile.
    """

    # Test expectations
    for i in range(len(expectations)):

        # Create step profile with a hole in the middle
        p = StepProfile()
        p.T, p.y = lib.unzip(profile)

        # Create filler
        f = StepProfile()
        f.T, f.y = lib.unzip(fillers[i])

        # Fill profile
        p.fill(f)

        # Every value on the y-axis should be defined
        # Expectations should be met
        assert all([y is not None for y in p.y])
        assert [p.T, p.y] == lib.unzip(expectations[i])
예제 #8
0
def test_inject():
    """
    Inject steps in profile according to given step durations. Tests 4 cases:
        - Step ends before start of next one (new step injected)
        - Step ends after start of next one (nothing to do)
        - Step is a canceling one (value is replaced by profile's zero value)
        - Step is at the end of profile (new step injected at the end) 
    """

    profile = [(getTime("00:00:00"), 6.2), (getTime("01:00:00"), 6),
               (getTime("01:30:00"), 5.8), (getTime("02:00:00"), 5.6),
               (getTime("03:00:00"), 5.4)]

    # Define zero (default y-axis value) for profile
    zero = 1000

    # Define durations for each given step
    durations = [datetime.timedelta(minutes=d) for d in [5, 60, 20, 0, 30]]

    # Define expected axes after injection
    expectations = [(getTime("00:00:00"), 6.2), (getTime("00:05:00"), zero),
                    (getTime("01:00:00"), 6), (getTime("01:30:00"), 5.8),
                    (getTime("01:50:00"), zero), (getTime("02:00:00"), zero),
                    (getTime("03:00:00"), 5.4), (getTime("03:30:00"), zero)]

    # Create step profile
    p = StepProfile()

    # Define it
    p.T, p.y = lib.unzip(profile)
    p.durations = durations
    p.zero = zero

    # Inject it with zeros
    p.inject()

    assert [p.T, p.y] == lib.unzip(expectations)
예제 #9
0
def test_map():
    """
    Create a daily profile, give it decoupled data and map it over range of days
    covered by said profile.
    """

    profile = [(getTime("00:30:00").time(), 1.30),
               (getTime("01:30:00").time(), 1.45),
               (getTime("02:30:00").time(), 1.60),
               (getTime("03:30:00").time(), 1.70),
               (getTime("04:30:00").time(), 1.80),
               (getTime("05:30:00").time(), 1.90),
               (getTime("06:30:00").time(), 2.00)]

    nDays = 3
    days = [
        getTime().date() + datetime.timedelta(days=d) for d in range(nDays)
    ]

    # Create profile
    p = DailyProfile()
    p.T, p.y = lib.unzip(profile)
    p.days = days

    # Map its data
    p.map()

    assert [p.T, p.y] == lib.unzip(
        sorted([(datetime.datetime.combine(d, T), y) for d in days
                for (T, y) in profile]))

    # Test before beginning of profile
    with pytest.raises(ValueError):
        p.f(getTime("00:00:00"))

    # Test midnight cross
    assert p.f(getTime("00:00:00") + datetime.timedelta(days=1)) == 2.00
예제 #10
0
    def decouple(self):
        """
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            DECOUPLE
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            Decouple profile data into components: convert string time values to
            datetime objects and get corresponding y-axis value.
        """

        # Info
        Logger.debug("Decoupling components of: " + repr(self))

        # Decouple data, convert string times to datetimes, and sort them in
        # chronological order
        [self.T, self.y] = lib.unzip([(lib.formatTime(T), y)
                                      for (T, y) in sorted(self.data.items())])
예제 #11
0
    def map(self):
        """
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            MAP
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            After decoupling daily profile data, reproduce it on the whole range
            of days that the profile covers.
        """

        # Info
        Logger.debug("Mapping time of: " + repr(self))

        # Map each time and value to profile's whole set of days
        mappedEntries = [(datetime.datetime.combine(day, T), y)
                         for (T, y) in zip(self.T, self.y)
                         for day in self.days]

        # Sort entries in chronological order and store them
        [self.T, self.y] = lib.unzip(sorted(mappedEntries))
예제 #12
0
def test_fill_empty():
    """
    Create a an empty step profile and try filling it with a filler.
    """

    # Create empty profile
    p = StepProfile()

    filler = [(getTime("01:00:00"), 6), (getTime("02:00:00"), 5.8),
              (getTime("04:00:00"), 5.6), (getTime("05:00:00"), 5.4)]

    # Create filler
    f = StepProfile()
    f.T, f.y = lib.unzip(filler)

    # Fill it
    p.fill(f)

    # Empty profile should be left empty after fill
    assert p.T == [] and p.y == []
예제 #13
0
def test_decouple():
    """
    Create a profile, give it data and decouple it into time and value axes.
    """

    # Create an unsorted profile
    profile = [(getTime("00:30:00", "1970.01.02"), 5.8),
               (getTime("23:30:00", "1970.01.01"), 6.2),
               (getTime("00:00:00", "1970.01.02"), 6),
               (getTime("01:00:00", "1970.01.02"), 5.6)]

    # Create profile
    p = Profile()
    p.data = dict([(lib.formatTime(d), y) for (d, y) in profile])

    # Decouple its data
    p.decouple()

    # Check profile axes (they should be time ordered)
    assert [p.T, p.y] == lib.unzip(sorted(profile))
예제 #14
0
def test_normalize():
    """
    Create a profile, then normalize its time axis.
    """

    profile = [(getTime("23:30:00", "1970.01.01"), 6.2),
               (getTime("00:00:00", "1970.01.02"), 6),
               (getTime("00:30:00", "1970.01.02"), 5.8),
               (getTime("00:00:00", "1970.01.03"), 5.6),
               (getTime("00:30:00", "1970.01.03"), 5.4),
               (getTime("00:00:00", "1970.01.04"), 5.2)]

    # Create profile and define its norm
    p = Profile()
    p.T, p.y = lib.unzip(profile)
    p.norm = p.T[-1]

    # Normalize it
    p.normalize()

    # Check normalization
    assert p.t == [lib.normalizeTime(T, p.norm) for T in p.T]
예제 #15
0
    def cut(self, a=None, b=None):
        """
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            CUT
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            Cut off all values that do not fit within [a, b]. Keep track of the
            last entry before start of profile.
        """

        # Info
        Logger.debug("Cutting: " + repr(self))

        # No start given
        if a is None:
            a = self.start

        # No end given
        if b is None:
            b = self.end

        # Test limit types
        if type(a) is not datetime.datetime or type(a) is not type(b):
            raise TypeError("Limit times to use while cutting profile have " +
                            "to be datetime objects.")

        # Group axes and filter them
        data = zip(self.T, self.y)
        olderData = [x for x in data if x[0] < a]
        filteredData = [x for x in data if a <= x[0] <= b]

        # Cut-off steps outside of start and end limits
        [self.T, self.y] = lib.unzip(filteredData)

        # Find last value before beginning of profile
        last = olderData[-1][1] if olderData else None

        # Return step value before beginning of profile
        return last
예제 #16
0
def do_test_op(op, base, profile, expectation):
    """
    Helper function to test operations on profiles.
    """
    def isEqual(x, y):
        return lib.isEqual(x, y, 0.001)

    wrongStart = base.start + datetime.timedelta(hours=1)
    wrongEnd = base.end - datetime.timedelta(hours=1)

    # Create a profile with mismatching limits
    wrongProfile = [(wrongStart, 0), (wrongEnd, 0)]

    w = StepProfile()
    w.T, w.y = lib.unzip(wrongProfile)
    w.start, w.end = wrongStart, wrongEnd
    w.norm = wrongEnd

    # Execute operation on profiles
    if op == "+":
        p = base.add(profile)

        with pytest.raises(errors.MismatchedLimits):
            base.add(w)

        with pytest.raises(errors.MismatchedLimits):
            w.add(base)

    elif op == "-":
        p = base.subtract(profile)

        with pytest.raises(errors.MismatchedLimits):
            base.subtract(w)

        with pytest.raises(errors.MismatchedLimits):
            w.subtract(base)

    elif op == "*":
        p = base.multiply(profile)

        with pytest.raises(errors.MismatchedLimits):
            base.multiply(w)

        with pytest.raises(errors.MismatchedLimits):
            w.multiply(base)

    elif op == "/":
        p = base.divide(profile)

        with pytest.raises(errors.MismatchedLimits):
            base.divide(w)

        with pytest.raises(errors.MismatchedLimits):
            w.divide(base)

    else:
        raise TypeError("Bad profile operation type.")

    assert all([
        T1 == T2 and isEqual(y1, y2)
        for ((T1, y1), (T2, y2)) in zip(expectation, zip(p.T, p.y))
    ])