dmarx / keyframed

Simple, expressive, pythonic datatypes for manipulating curves parameterized by keyframes and interpolators.
36 stars 1 forks source link

edge cases break curve addition #86

Closed dmarx closed 1 year ago

dmarx commented 1 year ago
from keyframed import Composition, Curve, ParameterGroup, SmoothCurve, SinusoidalCurve
import math
import matplotlib.pyplot as plt

low, high = 0, 0.3
step1 = 50
step2 = 2 * step1

# Define some curves, related through shared parameters.
# Each curve "bounces" back and forth between two keyframes, smoothly interpolating the intermediate values.
curves = ParameterGroup((
    #SmoothCurve({0:low,  step1:high},  bounce=True),
    SinusoidalCurve(wavelength=step1*2, phase=3*math.pi/2) ,#+ Curve(high/2),
    #SmoothCurve({0:high, step1:low}, bounce=True),
    SinusoidalCurve(wavelength=step1*2, phase=math.pi/2) ,#+ Curve(high/2),
    #SmoothCurve({0:low,  step2:high},  bounce=True),
    SinusoidalCurve(wavelength=step2*2, phase=3*math.pi/2) ,#+ Curve(high/2),
    #SmoothCurve({0:high, step2:low}, bounce=True),
    SinusoidalCurve(wavelength=step2*2, phase=math.pi/2) ,#+ Curve(high/2),
    #SinusoidalCurve(wavelength=step1*4, amplitude=high/2) + high/2

    #SinusoidalCurve(wavelength=step1, phase=math.pi),
    #SinusoidalCurve(wavelength=step2),
    #SinusoidalCurve(wavelength=step2, phase=math.pi),
))

#curves.plot(n=1000)
#plt.show()

# Define another curve implicitly, extrapolating from a function
#fancy = Curve.from_function(lambda k: high + math.sin(2*k/(step1+step2)))

#fancy = SinusoidalCurve(wavelength=(step2+step1)/math.pi) #+ .001 #Curve(1) #Curve(high),
#fancy = SinusoidalCurve(wavelength=(step2+step1)/math.pi) + Curve(high) # breaks
#fancy.plot(1000)
#fancy =  SinusoidalCurve(wavelength=(step2+step1)*math.pi) + high # the addition here just modifies the first keyframe
#fancy =  SinusoidalCurve(wavelength=(step2+step1)*math.pi) + Curve({0:high}) # maybe the issue here is conflicting keyframes?
fancy =  SinusoidalCurve(wavelength=(step2+step1)*math.pi)
#fancy.plot(1000)
#plt.show()

# arithmetic on curves
curves_plus_fancy = curves + fancy +1 + Curve(high) #+ Curve(high/2)
curves_summed_by_frame = Composition(curves_plus_fancy, reduction='sum')
really_fancy = curves_plus_fancy / curves_summed_by_frame

# isolate a single channel
## This breaks after modifying the implementation for "fancy"
channel_name = list(really_fancy[0].keys())[-1]
red_channel = Curve.from_function(lambda k: really_fancy[k][channel_name])

# built-in plotting
n = 1000
#really_fancy.plot(n=n) # this also broke after modifying "fancy"
really_fancy.plot(xs=list(range(1000))) # still broken
red_channel.plot(n=n, linewidth=3, linestyle='-', color='#d62728')

plt.gca().axis('off')
plt.tight_layout()
#plt.savefig('static/images/fancy.png')
plt.show()
dmarx commented 1 year ago